Cyber Security

SQL Injection — Demo Attack dan Cara Mitigasi untuk Developer

SQL Injection — Demo Attack dan Cara Mitigasi untuk Developer

Pernah dengar cerita soal website besar yang diretas karena ada satu baris kode yang "lupa" dicek? Di dunia cybersecurity, ada satu jenis serangan yang sudah berusia lebih dari dua dekade tapi masih masuk daftar OWASP Top 10 tahun 2025 — SQL Injection. Bukan karena teknologinya canggih, tapi karena developer masih sering melupakan hal dasar. Artikel ini akan membahas SQL Injection dari sudut pandang developer: apa itu, bagaimana serangannya terjadi, dan yang paling penting — bagaimana cara mencegahnya.

SQL Injection: Pintu Samping yang Terbuka

Bayangkan kamu punya rumah dengan pintu depan yang sudah dikunci rapat — firewall aktif, HTTPS terpasang, autentikasi berjalan. Tapi ternyata ada jendela di belakang yang tidak dikunci. Itulah kira-kira analogi SQL Injection. Serangan ini tidak menembus firewall atau bypass enkripsi. Ia masuk melalui input yang kamu terima dari user — input yang seharusnya kamu validasi tapi tidak kamu lakukan.

SQL Injection bekerja dengan cara menyisipkan kode SQL berbahaya ke dalam input yang seharusnya hanya berupa teks biasa. Jika aplikasi kamu langsung memasukkan input user ke dalam query database tanpa sanitasi, attacker bisa "membajak" query tersebut. Hasilnya? Bisa berupa pencurian data, penghapusan data, bahkan kontrol penuh atas database server kamu.

Bagaimana Serangan SQL Injection Terjadi

Mari kita lihat contoh sederhana. Misalnya kamu punya form login sederhana:

<?php
$username = $_POST['username'];
$password = $_POST['password'];

$query = "SELECT * FROM users WHERE username='$username' AND password='$password'";
$result = mysqli_query($conn, $query);
?>

Kode di atas terlihat "normal" untuk banyak developer pemula. Tapi perhatikan bahwa variabel $username dan $password langsung dimasukkan ke dalam query tanpa ada sanitasi sama sekali. Ini adalah resep untuk bencana.

Sekarang bayangkan attacker memasukkan admin' -- di field username. Query yang dihasilkan menjadi:

SELECT * FROM users WHERE username='admin' --' AND password=''

Tanda -- di SQL adalah komentar. Jadi bagian password dicek, dan query hanya memeriksa apakah username admin ada. Tanpa autentikasi yang sebenarnya, attacker masuk ke akun admin. Ini disebut authentication bypass — salah satu bentuk SQL Injection paling klasik.

Jenis-Jenis SQL Injection

SQL Injection tidak selalu sesederhana contoh di atas. Berikut beberapa variasi yang perlu kamu kenali:

In-band SQL Injection adalah tipe paling umum, di mana attacker melihat hasil query langsung di response aplikasi. Contohnya error message yang menampilkan struktur database, atau halaman yang berubah perilaku berdasarkan input berbahaya. Ini termasuk UNION-based (menggabungkan hasil query berbahaya dengan query asli) dan Error-based (menggunakan error message untuk mengekstrak informasi).

Blind SQL Injection terjadi ketika aplikasi tidak menampilkan error atau hasil query secara langsung. Attacker harus "mengintip" jawaban dari pertanyaan boolean yang diajukan. Misalnya, dengan mengirim ' OR 1=1 -- dan mengamati perbedaan respons antara true dan false. Prosesnya lebih lambat tapi sama berbahayanya.

Out-of-band SQL Injection menggunakan fitur-fitur database seperti LOAD_FILE() atau UTL_HTTP.REQUEST untuk mengirim data keluar dari database ke server attacker. Tipe ini lebih jarang karena membutuhkan fitur database yang spesifik, tapi sulit dideteksi.

Demo Praktis: SQL Injection di PHP

Mari kita coba demo sederhana. Buat file PHP dengan query rentan injection:

<?php
$conn = new mysqli('localhost', 'root', 'password', 'testdb');

if (isset($_GET['id'])) {
    // VULNERABLE — jangan tiru ini!
    $id = $_GET['id'];
    $query = "SELECT name, email FROM users WHERE id = $id";
    $result = $conn->query($query);

    while ($row = $result->fetch_assoc()) {
        echo "Name: " . $row['name'] . "<br>";
        echo "Email: " . $row['email'] . "<br>";
    }
}
?>

Jika URL biasa adalah example.com/user.php?id=1, attacker bisa mencoba:

# Menampilkan semua data
example.com/user.php?id=1 UNION SELECT username, password FROM users--

# Menyuntikkan data palsu (INSERT)
example.com/user.php?id=1; INSERT INTO users(name,email) VALUES('hacker','[email protected]')--

# Menghapus tabel
example.com/user.php?id=1; DROP TABLE users--

Coba bayangkan ini terjadi di website yang menyimpan data kartu kredit, riwayat medis, atau identitas nasional. Dampaknya bisa sangat besar.

Cara Mencegah SQL Injection

Kabar baiknya, SQL Injection termasuk serangan yang sangat mudah dicegah asalkan kamu tahu caranya. Berikut metode-metode yang sudah terbukti efektif:

1. Prepared Statements (Parameterized Queries)

Ini adalah cara paling efektif dan paling direkomendasikan. Prepared statements memisahkan query SQL dari data, sehingga input user tidak pernah diinterpretasikan sebagai kode SQL.

<?php
// SAFE — gunakan prepared statements
$stmt = $conn->prepare("SELECT name, email FROM users WHERE id = ?");
$stmt->bind_param("i", $_GET['id']);
$stmt->execute();
$result = $stmt->get_result();

while ($row = $result->fetch_assoc()) {
    echo "Name: " . $row['name'] . "<br>";
    echo "Email: " . $row['email'] . "<br>";
}
?>

Perhatikan tanda tanya ? di query — itu adalah placeholder yang akan diisi oleh bind_param(). Database hanya akan memperlakukan nilai tersebut sebagai data, bukan sebagai bagian dari struktur query. Serangan SQL Injection menjadi sia-sia.

2. Input Validation

Selain prepared statements, kamu juga harus memvalidasi input user. Jika field harus berupa angka, pastikan memang angka. Jika harus email, validasi format email. Jangan pernah mempercayai input apa adanya.

<?php
// Validasi: pastikan ID hanya angka
$id = filter_input(INPUT_GET, 'id', FILTER_VALIDATE_INT);
if ($id === false) {
    die("Invalid ID");
}

// Sekarang aman untuk dimasukkan ke query
$stmt = $conn->prepare("SELECT name, email FROM users WHERE id = ?");
$stmt->bind_param("i", $id);
?>

3. Stored Procedures

Stored procedures adalah blok SQL yang disimpan di database dan dieksekusi dari aplikasi. Dengan stored procedures, query kompleks tidak perlu ditulis langsung di kode aplikasi, dan kamu bisa membatasi权限 yang dibutuhkan oleh user database.

4. Whitelist Approach

Jika input hanya bisa berupa beberapa nilai tertentu (misalnya role: admin, editor, viewer), gunakan whitelist. Bandingkan input dengan daftar nilai yang diizinkan, bukan dengan daftar nilai yang dilarang.

<?php
$allowed_roles = ['admin', 'editor', 'viewer'];
$role = $_POST['role'];

if (!in_array($role, $allowed_roles)) {
    die("Role tidak valid");
}
?>

5. Least Privilege Principle

Gunakan user database dengan hak akses seminimal mungkin. Jika aplikasi hanya perlu membaca data, jangan gunakan user dengan hak DROP atau GRANT. Bahkan jika ada injection, dampaknya bisa dibatasi.

Tools Deteksi SQL Injection

Selain mencegah dari sisi kode, kamu juga bisa menggunakan tools untuk mendeteksi kerentanan SQL Injection di aplikasi kamu:

sqlmap adalah tool otomatis yang bisa mendeteksi dan mengeksploitasi SQL Injection. Sangat berguna untuk testing aplikasi sendiri. Jalankan scan terhadap aplikasi lokal sebelum deploy ke production.

Burp Suite (Community Edition gratis) bisa digunakan untuk intercept dan memodifikasi request HTTP, sehingga kamu bisa menguji input secara manual.

Nikto adalah web server scanner yang bisa mendeteksi beberapa jenis kerentanan termasuk SQL Injection di level configuration.

Ingat: gunakan tools ini hanya untuk testing aplikasi milik kamu sendiri. Menggunakan tools ini terhadap aplikasi orang lain tanpa izin adalah tindakan ilegal.

Kesimpulan

SQL Injection mungkin terdengar seperti topik "klasik" yang sudah ketinggalan zaman, tapi kenyataannya serangan ini masih sangat relevan di tahun 2025. Banyak sekali kasus kebocoran data yang disebabkan oleh hal sesederhana "lupa pakai prepared statements."

Sebagai developer, kamu punya tanggung jawab untuk melindungi data user. Mulai dari sekarang, pastikan setiap query yang kamu tulis menggunakan prepared statements, setiap input yang kamu terima sudah divalidasi, dan setiap user database sudah diberikan hak akses seminimal mungkin.

Apakah kamu pernah menemui kerentanan SQL Injection di proyek kamu? Atau mungkin punya tips tambahan soal pencegahan? Ceritakan di kolom komentar — siapa tahu pengalaman kamu bisa membantu developer lain.