SQL injection adalah celah di mana input user yang seharusnya sebuah data (nama, angka) ikut dibaca database sebagai bagian dari perintah SQL, karena input itu disambung langsung ke teks query. Bayangin formulir yang kalimatnya belum selesai: "ambil data user dengan nama ___". Kalau isian namanya ditulis "siapa pun", kalimatnya berubah arti, dan database menuruti arti yang baru itu. Ini salah satu celah tertua dan masih paling sering ditemukan.
🧪 Tebakan cepat: query
SELECT * FROM users WHERE username = '<input>'diberi input' OR 1=1 --. Berapa baris yang kembali dari tabel berisi tiga user? Tebak dulu, jawabannya ada di bagian "Teknik OR 1=1: WHERE selalu benar".
Bagaimana SQL injection bekerja
Query yang rentan menyusun SQL dengan menyambung (concatenation) input user ke dalam teks query:
// RENTAN: input disambung ke teks query
$username = $_GET["username"];
$query = "SELECT * FROM users WHERE username = '$username'";
Kalau username berisi budi, query jadi ... WHERE username = 'budi', benar. Tapi username datang dari user, dan user bisa mengetik apa saja. Masalahnya muncul kalau input mengandung tanda kutip ': kutip itu menutup string lebih cepat, dan sisa input setelahnya dibaca database sebagai SQL, bukan sebagai data.
Teknik OR 1=1: WHERE selalu benar
Teknik injeksi paling dasar menyisipkan OR 1=1 ke klausa WHERE. Misalnya tabel users berisi tiga baris: admin, budi, dan siti. Dengan input ' OR 1=1 --, teks query-nya berubah jadi:
SELECT * FROM users WHERE username = '' OR 1=1 --'
- Kutip di awal input menutup string
username, laluOR 1=1disambung sebagai syarat tambahan. 1=1selalu bernilai benar, jadiusername = '' OR 1=1benar untuk setiap baris.--memulai komentar SQL, jadi sisa query asli (kutip penutup yang menggantung) diabaikan.- Hasilnya: WHERE cocok untuk semua baris, jadi ketiga user kembali,
admin,budi,siti. Itu jawaban tebakannya: tiga baris, seluruh tabel.
Yang seharusnya mengambil satu user malah membocorkan semuanya, karena input berubah jadi bagian dari perintah.
Tanda dan dampak
Tanda sederhana sebuah query rentan: kalau menambahkan satu ' di input memunculkan error SQL, kemungkinan besar input kamu ikut dibaca sebagai query. Dampaknya nyata:
- Bypass autentikasi: login tanpa password yang benar, dengan membuat WHERE selalu benar.
- Pencurian data: teknik union-based menambahkan
UNION SELECTuntuk menarik data dari tabel lain ke dalam hasil, misalnya mengambil username dan password dari tabeluserslewat halaman produk. - Modifikasi atau penghapusan data: dalam kasus tertentu, injeksi bisa mengubah atau menghapus baris.
Pencegahan singkat
Akar masalahnya satu: input user disambung ke teks query. Perbaikannya juga satu: jangan pernah menyambung input ke query. Pakai parameterized query dengan placeholder, dan kirim nilainya terpisah:
$stmt = $pdo->prepare("SELECT * FROM users WHERE username = ?");
$stmt->execute([$username]);
Dengan cara ini, ' OR 1=1 -- dicari sebagai username literal, gak ketemu, dan mengembalikan 0 baris. Cara menulis query aman ini dibahas tuntas di lesson berikutnya, SQL Injection Prevention.
⚠️ Jebakan yang sering ketemu
- Mengira input "pasti" nama biasa. Input dari URL, form, header, dan cookie bisa berisi apa saja, termasuk kutip dan kata kunci SQL.
- Menyembunyikan error SQL dianggap cukup. Menyembunyikan pesan error mempersulit penyerang, tapi gak menutup celahnya. Query-nya tetap rentan.
- Menyaring kata seperti
ORatau--. Daftar larangan selalu bisa diakali. Yang menutup celah adalah memisahkan query dari data, bukan menebak input jahat. - Mengira celah ini sudah kuno. SQL injection masih sering ditemukan sampai sekarang, terutama di kode yang menyusun query dengan string.
TL;DR: SQL injection terjadi kalau input user disambung ke teks query, sehingga ikut dibaca sebagai perintah SQL. Input ' OR 1=1 -- pada SELECT * FROM users WHERE username = '<input>' membuat WHERE selalu benar, jadi seluruh tabel (admin, budi, siti) kembali, bukan satu baris. Tanda rentan: menambah satu ' memunculkan error SQL. Dampaknya bypass autentikasi, pencurian data (union-based), sampai modifikasi data. Pencegahannya: jangan sambung input ke query, pakai parameterized query dengan placeholder ?, yang dibahas tuntas di lesson berikutnya.