August 24, 2026
Belajar VAPT #3: Membongkar Jumlah Kolom Database dengan SQL Injection UNION Attack
1. Overview & Scope

By BIT Journal
4 min read
Dalam serangan UNION-based SQL Injection, teknik UNION digunakan untuk menggabungkan hasil dari kueri SQL buatan penyerang (attacker) dengan kueri asli yang dijalankan oleh aplikasi web. Namun, agar eksekusi UNION berhasil tanpa memicu error dari database, penyerang harus memenuhi dua syarat utama:
· Kueri buatan harus mengembalikan jumlah kolom yang sama dengan kueri asli.
· Tipe data pada tiap kolom yang sejajar harus kompatibel.
Tahap paling awal sebelum melakukan ekstraksi data adalah menentukan jumlah kolom yang dikembalikan oleh kueri asli database.
a. Target
Halaman kategori produk PortSwigger Web Security Academy (Lab: SQL injection UNION attack, determining the number of columns returned by the query).
b. Fokus Pengujian
Parameter category pada URL filter produk (/filter?category=).
c. Dampak Kerentanan
Pengungkapan informasi (Information Disclosure) yang menjadi batu loncatan untuk data extraction penuh dari tabel database.
- Reconnaissance
Tahap awal dimulai dengan mengeksplorasi alur kerja pada aplikasi target, yaitu website e-Commerce. Dilakukan eksplorasi meliputi akses semua menu dan form yang tersedia.
Tidak ditemukan celah saat mengirimkan payload di parameter login dan id product. Namun, ditemukan sesuatu yang menarik ketika mencoba pencarian produk berdasarkan kategori. Saat memilih salah satu kategori (misalnya Corporate gifts), aplikasi mengirimkan request HTTP GET berikut:
GET /filter?category=Accessories HTTP/2
Secara logika di sisi backend, kueri SQL yang digunakan untuk mengambil data produk dari database diperkirakan seperti ini:
SELECT name, description, category FROM products WHERE category = 'Corporate gifts' AND released = 1
- Vulnerability Identification
Untuk menguji keberadaan celah SQLi pada parameter category, saya mencegat (intercept) lalu lintas menggunakan Burp Suite dan menyisipkan karakter petik satu (') pada parameter category.
Input yang diuji: category= Accessories'
Hasilnya, server merespons dengan indikasi kesalahan sintaks kueri (Internal Server Error). Ini menandakan bahwa karakter petik satu berhasil lolos tanpa disanitasi dan mematahkan pembatas string (string literal) kueri SQL asli di backend. Kondisi ini mengonfirmasi bahwa parameter category rentan terhadap SQL Injection karena tidak menggunakan parameterized queries. Hal ini membuka celah bagi attacker untuk menginterupsi logika query SQL asli dan menyisipkan perintah buatan sendiri.
Munculnya 500 Internal Server Error, terutama saat pengguna memasukkan karakter khusus seperti ', ", atau
a. Internal Server Error = Titik Awal Investigasi (Bukan Hasil Akhir)
Mendapatkan HTTP 500 berarti kamu sudah membentur celah (finding an entry point). Tugas kamu selanjutnya adalah menyesuaikan payload agar perintah buatanmu dapat dieksekusi dengan sukses tanpa membuat server crash (mengubah status respons dari 500 kembali ke 200 OK dengan hasil eksploitasi).
b. Dampak Tambahan (Verbose Error Message)
Kadang, selain HTTP 500, server yang tidak aman juga menampilkan pesan error detail di layar (misal: Uncaught SyntaxError: SQL state [42000] in PostgreSQL…). Ini disebut kerentanan Information Disclosure, yang memberikan petunjuk gratis kepada pentester/attacker tentang jenis database dan struktur kueri yang digunakan backend.
- Exploitation (PoC)
Untuk menentukan jumlah kolom yang di-SELECT oleh kueri asli, dapat digunakan teknik ORDER BY. Klausa ORDER BY dalam SQL mengurutkan hasil berdasarkan indeks kolom (1, 2, 3, dst.). Jika indeks kolom yang dimasukkan melebihi jumlah kolom asli, database akan melemparkan kesalahan (error).
a. Pengujian dengan ORDER BY:
-
…/filter?category=Corporate gifts' ORDER BY 1 — → HTTP 200 OK
-
…/filter?category=Corporate gifts' ORDER BY 2 — → HTTP 200 OK
-
…/filter?category=Corporate gifts' ORDER BY 3 — → HTTP 200 OK
-
…/filter?category=Corporate gifts' ORDER BY 4 — → HTTP 500 Internal Server Error
b. Analisis:
Ketika menyisipkan ORDER BY 4, server merespons dengan status 500 Internal Server Error. Ini mengindikasikan bahwa tabel/kueri asli hanya memiliki 3 kolom.
Setelah memperkirakan bahwa kueri asli mengembalikan 3 kolom menggunakan ORDER BY, langkah berikutnya adalah memverifikasi jumlah tersebut secara pasti menggunakan payload UNION SELECT. Nilai NULL digunakan dalam pengujian UNION SELECT karena NULL bersifat netral dan kompatibel dengan semua tipe data (seperti Integer, String/Varchar, Boolean, maupun Date).
Langkah Eksekusi:
a. Cegat (intercept) filter kategori produk pada browser/Burp Suite.
b. Kirim request tersebut ke Burp Suite Repeater untuk eksperimen payload.
c. Modifikasi nilai parameter category menjadi:
' UNION SELECT NULL — ' UNION SELECT NULL,NULL — ' UNION SELECT NULL,NULL,NULL — dst.
Analisis Payload:
Kueri SQL di sisi backend dieksekusi menjadi:
SELECT name, description, category FROM products WHERE category = '' UNION SELECT NULL, NULL, NULL — ' AND released = 1
· Karakter ' mematahkan string pembatas parameter category. · Operator UNION SELECT NULL, NULL, NULL menggabungkan hasil kueri asli dengan 3 kolom bernilai NULL. · Tanda — mematikan sisa kueri SQL bawaan di belakangnya.
Hasil (Result):
Server merespons dengan status HTTP 200 OK dan halaman web menampilkan produk tanpa error. Hal ini secara pasti mengonfirmasi bahwa kueri asli aplikasi web mengembalikan 3 kolom, dan lab dinyatakan Solved.
- Remediation
Mengetahui jumlah kolom adalah "pintu gerbang" paling penting dalam serangan UNION SQLi. Jika langkah ini berhasil, attacker tinggal mencari tahu kolom mana yang bertipe string untuk kemudian dipakai menyedot data sensitif seperti tabel users.
Sebagai praktisi keamanan maupun pengembang web, celah berbahaya ini sebenarnya sangat mudah dicegah:
a. Gunakan Prepared Statements (Parameterized Queries)
Ini adalah hukum wajib. Jangan pernah memisahkan atau menggabungkan input pengguna secara langsung ke dalam sintaks SQL. Gunakan placeholder (?) agar input pengguna selalu diperlakukan murni sebagai data, bukan instruksi program.
b. Batasi Informasi Error (Disable Verbose Error)
Jangan menampilkan detail kesalahan database atau status error 500 secara mentah ke pengguna karena informasi tersebut memberikan petunjuk berharga bagi penyerang.