Skip to main content
  1. Concetti/

SQL Injection (SQLi)

·4 mins
Alessio Barnini
Author
Alessio Barnini
Table of Contents

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:

  1. Inserimento ' → genera errore di sintassi, confermando la vulnerabilita'.
  2. Inserimento '-- → commenta il resto della query, eliminando restrizioni (es. released=1).
  3. Inserimento ' OR 1=1-- → forza la condizione a True, estraendo tutti i dati.

Esempio progressivo:

Query originale:

SELECT * FROM products WHERE category = 'Gifts' AND released = 1

Test vulnerabilita' (single quote):

SELECT * FROM products WHERE category = ''' AND released = 1
-- Errore di sintassi: quote dispari

Bypass restrizioni (commento):

SELECT * FROM products WHERE category = 'Gifts'--' AND released = 1
-- Tutto cio' che segue '--' viene ignorato

Estrazione totale (tautologia):

SELECT * FROM products WHERE category = '' OR 1=1--' AND released = 1
-- OR 1=1 e' sempre vera: restituisce tutte le righe

Elementi 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.

TipoMeccanismoQuando si usa
Union-basedUNION SELECT aggancia query aggiuntiveRisposta visibile + si conosce numero di colonne
Error-basedMessaggi errore DB rivelano datiDB espone errori dettagliati
Boolean-basedComportamento app true vs falseNessun output diretto
Time-basedSLEEP(5) per inferireApp non rivela nulla, solo timing
Out-of-bandEsfiltrazione via DNS/HTTPTutti 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 controllo AND password = ''.
  • L'1=1 (Tautologia): nel Caso B, non sapendo chi sia l'utente admin, OR 1=1 forza WHERE 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 $id contiene ' 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

Related