SQL Injection (SQLi) è un pratica informatica in cui un utente malintenzionato può eseguire istruzioni SQL maligne prendendo il controllo del database di un’applicazione web. SQL Injection può influenzare qualsiasi sito o applicazione Web che prevede l’utilizzo di un database basato su linguaggio SQL.
Questa è una tra le vulnerabilità più consolidate, più pervasive e più pericolose. Infatti, un utente malintenzionato, attraverso l’SQL Injection, può aggirare le procedure di autenticazione, verifica e approvazione di un’applicazione Web e recuperare in sostanza un intero database. SQL Injection può anche essere usato per inserire, alterare e cancellare record in un database, influenzando la correttezza delle informazioni. Nel peggiore dei casi, SQL Injection può fornire a un utente malintenzionato l’accesso non autorizzato a dati sensibili, tra cui informazioni sui clienti, dati identificativi, password e altri dati sensibili.
Come funziona l’SQL Injection?
Prima di poter eseguire richieste SQL maligne su un database, un utente dovrebbe prima scoprire il meccanismo di richieste POST o GET di uno script Web che incorpora all’interno una richiesta SQL al server. Con pochi semplici passaggi, un utente smanettone potrebbe già essere in grado di incorporare del codice malevolo in una richiesta ufficiale. Tale richiesta sarà eseguita dal server come se fosse una normale richiesta eseguita attraverso un form di dati.
L’esempio riportato è molto semplice: mostra come un utente malintenzionato può utilizzare una vulnerabilità di SQL Injection per aggirare la sicurezza delle applicazioni e autenticarsi come amministratore. l seguente script è uno pseudo-codice eseguito su un ipotetico server web. È un semplice esempio di autenticazione con username e password. Il database di esempio ha una tabella denominata users con le seguenti colonne: username e password e viene eseguita una query per selezionare un id corrispondente ai parametri passati
uname = request.POST['username']
passwd = request.POST['password']
# SQL query vulnerabile a SQLi
sql = “SELECT id FROM users WHERE username=’” + uname + “’ AND password=’” + passwd + “’”
# Esecuzione del comando
database.execute(sql)
Questi campi di input sono vulnerabili a SQL Injection. Un utente malintenzionato può utilizzare i comandi SQL nell’input in modo da alterare l’istruzione SQL eseguita dal server di database. Ad esempio, potrebbero usare il classico trucco che utilizza un singolo apostrofo e impostare il campo password su:
password' OR 1=1
Di conseguenza, il server database esegue la seguente query SQL:
SELECT id FROM users WHERE username='username' AND password='password' OR 1=1'
A causa della condizione tautologica OR 1=1 che risulta essere sempre vera, la query restituisce il primo id dalla tabella users, non importa quale sia username e password. Il primo utente id in un database è molto spesso l’amministratore. In questo modo, il malintenzionato non solo ignora l’autenticazione ma ottiene anche i privilegi di amministratore. Possono anche commentare il resto dell’istruzione SQL per controllare ulteriormente l’esecuzione della query SQL:
-- MySQL, MSSQL, Oracle, PostgreSQL, SQLite
' OR '1'='1' --
' OR '1'='1' /*
-- MySQL
' OR '1'='1' #
-- Access
' OR '1'='1' %00
' OR '1'='1' %16
Anatomia di un attacco SQL Injection
Un attacco SQL Injection necessita solo di due condizioni: un database SQL e un client in grado di inviare porzioni personalizzate di query SQL. Eseguire una query SQL malevola opportunamente rimaneggiata, fa sballare il motore del database, provocando un’eccezione o un errore.
Gli errori sono sicuramente utili per i programmatori in fase di sviluppo, tuttavia, nel caso in cui siano abilitati su un sito già pubblicato, possono svelare una considerevole quantità di informazioni a un utente malintenzionato, al punto tale da acquisire dati anche sulla struttura del database, i nomi dei campi e delle tabelle. Con queste informazioni si potranno poi fare altre query per ottenere altre informazioni più sensibili e delicate, oppure per modificare dei record o addirittura eliminare delle informazioni specifiche contenute nelle tabelle.
Come prevenire attacchi SQL Injection
L’unico modo sicuro per prevenire gli attacchi SQL Injection è la convalida dell’input e le query parametrizzate, comprese le istruzioni preparate. Il codice dell’applicazione non deve mai utilizzare direttamente l’input. Lo sviluppatore deve disinfettare tutti gli input, non solo gli input dei moduli Web come i moduli di accesso. Deve rimuovere potenziali elementi di codice dannoso come le singole virgolette e gli apostrofi. È anche una buona idea disattivare la visibilità degli errori del database sui siti di produzione perchè gli errori del database possono essere utilizzati con SQL Injection per ottenere informazioni sulla struttura delle tabelle del database.
Per fare un po’ di prevenzione su attacchi SQL Injection sul proprio sito è cosa buona e giusta consultare una guida come ad esempio questa: Bobby Tables: A guide to preventing SQL injection.