Cos'e'#
La SQL Injection sfrutta la mancanza di separazione tra dati e istruzioni nella costruzione delle query. Un attaccante inserisce codice SQL nel campo di input e il database lo esegue come se fosse parte della query originale.
Una vulnerabilita' di sicurezza che permette a un attaccante di interferire con le query che un'applicazione effettua al suo database, accedendo a dati non autorizzati.
TL;DR#
La SQLi sfrutta la mancanza di sanificazione dell'input. Inserendo una single quote ('), l'attaccante chiude la stringa prevista dallo sviluppatore e inietta codice SQL arbitrario.
Flusso d'attacco:
- Inserimento
'→ genera errore di sintassi, confermando la vulnerabilita'. - Inserimento
'--→ commenta il resto della query, eliminando restrizioni (es.released=1). - Inserimento
' OR 1=1--→ forza la condizione aTrue, estraendo tutti i dati.
Esempio progressivo:
Query originale:
SELECT * FROM products WHERE category = 'Gifts' AND released = 1Test vulnerabilita' (single quote):
SELECT * FROM products WHERE category = ''' AND released = 1
-- Errore di sintassi: quote dispariBypass restrizioni (commento):
SELECT * FROM products WHERE category = 'Gifts'--' AND released = 1
-- Tutto cio' che segue '--' viene ignoratoEstrazione totale (tautologia):
SELECT * FROM products WHERE category = '' OR 1=1--' AND released = 1
-- OR 1=1 e' sempre vera: restituisce tutte le righeElementi chiave#
- Single Quote (
'): il grimaldello per rompere la query. - Commento (
--): neutralizza la logica successiva della query originale (filtri di sicurezza, controlli password). - Tautologia (
OR 1=1): condizione logica sempre vera che forza il database a restituire ogni riga della tabella.
Tipi di SQLi#
Tre famiglie principali, distinte da come l'attaccante riceve il risultato dell'iniezione.
| Tipo | Meccanismo | Quando si usa |
|---|---|---|
| Union-based | UNION SELECT aggancia query aggiuntive | Risposta visibile + si conosce numero di colonne |
| Error-based | Messaggi errore DB rivelano dati | DB espone errori dettagliati |
| Boolean-based | Comportamento app true vs false | Nessun output diretto |
| Time-based | SLEEP(5) per inferire | App non rivela nulla, solo timing |
| Out-of-band | Esfiltrazione via DNS/HTTP | Tutti gli altri metodi bloccati |
Come funziona#
L'attaccante rompe il contesto dei dati per inserire comandi SQL arbitrari. La concatenazione di stringhe e' il vettore: il database non distingue input dati da istruzioni.
Esempio: bypass del login con username noto:
Form compilato dall'attaccante:
<!-- Username: administrator'-- -->
<!-- Password: (vuoto) -->Via curl:
# Caso A: username noto
curl -X POST http://sito-vulnerabile.com/login \
-d "username=administrator'--" \
-d "password="
# Caso B: username ignoto (tautologia)
curl -X POST http://sito-vulnerabile.com/login \
-d "username=' OR 1=1--" \
-d "password="Query originale:
SELECT * FROM users WHERE username = '$USERNAME' AND password = '$PASSWORD'Query iniettata (Caso A):
SELECT * FROM users WHERE username = 'administrator'--' AND password = ''Query iniettata (Caso B, tautologia):
SELECT * FROM users WHERE username = '' OR 1=1--' AND password = ''Cosa accade esattamente:
- L'apice (
'): chiude forzatamente la stringa che il programmatore aveva aperto per leggere l'input. - I trattini (
--): dicono al database "ignora tutto il resto della riga", cancellando il controlloAND password = ''. - L'1=1 (Tautologia): nel Caso B, non sapendo chi sia l'utente admin,
OR 1=1forzaWHERE falso OR vero→ vero per ogni utente. Il database restituisce tutta la lista utenti e la web app fa loggare il primo -- spesso l'amministratore, creato per primo.
Perche' e' importante per Blue Team#
Come difensori, il lavoro e' assicurarsi che gli sviluppatori usino query parametrizzate (Prepared Statements) e monitorare i log per individuare pattern sospetti.
Dev parallel: La differenza tra sanitization e parametrization e' fondamentale. In PHP raw,
$_GET['id']concatenato nella query e' il disastro:"SELECT * FROM users WHERE id = " . $_GET['id']. La sanitization (filtrare l'input) e' un secondo livello ma non e' sufficiente -- un attaccante creativo trova sempre un encoding che passa il filtro. La parametrization separa struttura dei dati dalle istruzioni a livello di protocollo:// Pericoloso -- mai farlo $query = "SELECT * FROM users WHERE id = " . $_GET['id']; // Sicuro con PDO $stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?"); $stmt->execute([$id]); // Symfony/Doctrine -- prepared statements automatici $repo->findBy(['id' => $id]); // oppure con DQL $em->createQuery("SELECT u FROM User u WHERE u.id = :id") ->setParameter('id', $id);Con i prepared statements il database riceve la struttura della query separata dai dati. Anche se
$idcontiene' OR 1=1--, viene trattato come stringa letterale -- non puo' rompere la struttura SQL.
Dove l'ho incontrato#
- tryhackme-sql-injection -- laboratorio pratico
- portswigger-academy -- approfondimento teorico
Scenario Reale#
Un analista SOC nota nei log del WAF numerose richieste verso /login contenenti la stringa %27%20OR%201%3D1. Questo indica un tentativo di bypass dell'autenticazione. Se l'applicazione non usa query parametrizzate, l'attaccante potrebbe ottenere l'accesso come amministratore semplicemente conoscendo lo username.
Risorse#
Collegato a#
- owasp-top10 -- A03 Injection, categoria padre
- xss -- altra vulnerabilita' da input non validato


