SQL injection: come funziona, come proteggersi

SQL injection: come funziona,
come proteggersi
Gli scarsi controlli nell’interfaccia SQL con il data base consentono
attacchi molto pericolosi.
M.R.A. Bozzetti, OAI founder
In questa stessa rubrica, circa un anno fa, nell’articolo I dieci
principali errori nella programmazione che causano vulnerabilità , avevo commentato i principali errori di programmazione che generano vulnerabilità negli applicativi
e che sono i principali mezzi che consentono attacchi. Al
secondo posto si ponevano gli scarsi controlli nell’interazione con banche dati tramite SQL, Structured Query Language, che consentono attacchi tipo SQL injection, una tecnica che sfrutta gli scarsi controlli in un’interrogazione SQL
a una banca dati.
Molti dei recenti attacchi, come quello a Sony, hanno usato
questa tecnica, come riferito in precedenti articoli di questa rubrica. Per questo motivo ho ritenuto opportuno chiarire cosa
sia, come funziona, e come sia possibile evitare attacchi di
questi genere; pur non entrando in dettagli, questo articolo è
più tecnico rispetto al consueto taglio informativo e manageriale della rubrica OAI.
Per comprendere a grandi linee come funziona un attacco
con SQL injection, per brevità indicato con SQLIA (SQL Injection Attack), è necessario comprendere il contesto nel
quale opera. SQL è un linguaggio di interrogazione di una
banca dati di tipo relazionale. È divenuto standard ANSI
e ISO, ed è così diffuso e consolidato che alcuni database
hanno questo acronimo nel loro nome: si pensi a MySQL e
a Microsoft SQL Server. In un database relazionale i dati
sono rappresentati come relazioni in tabelle e manipolati
con gli operatori dell’algebra relazionale: operatori di confronto, aritmetici, condizionali e logici. SQL è un linguaggio dichiarativo: le istruzioni SQL consentono di leggere,
modificare, cancellare i dati e di espletare funzioni gestio-
88
office automation
luglio-agosto 2011
nali e amministrative. Esse sono strutturate nei seguenti sottosistemi:
• DDL, Data Definition Language, per creare, cancellare e
modificare la struttura di un database;
• DML, Data Manipulation Language, per inserire, cancellare e modificare i dati; tipiche istruzioni sono <select>, <insert>, <update>, <delete>;
• DCL Data Control Language, per gestire gli utenti e i loro
diritti;
• QL, Query Language, permette di interrogare il database,
cioè di leggere i dati;
• DMCL, Device Media Control Language, per gestire lo storage dove sono memorizzati i database.
L’utilizzo delle istruzioni SQL con i relativi operatori può essere
effettuata direttamente dall’amministratore del database con interfaccia a singolo comando o di tipo grafico (GUI), oppure
tramite linguaggi di programmazione o script.
Per sviluppare pagine web dinamiche esistono vari strumenti
e linguaggi, i più diffusi sono PHP (Hypertext Preprocessor) in
ambito Linux e ASP (Active Server Pages: sono pagine web che
oltre al codice HTML contengono script che vengono eseguiti
dal web server Microsoft IIS) in ambito Microsoft. I vari linguaggi di programmazione utilizzano delle API, Appication
Program Interface, per inserire le istruzioni SQL e interfacciarsi
ai database.
Diverse possono essere le modalità di attacco SQLIA a un’applicazione web, ma tutte si basano sulla mancanza, totale o
parziale, di controlli sui dati di input. Si consideri il semplice
esempio (derivato da Wikipedia) di un form di login da un
browser a una applicazione web tramite verifica dell’identificativo dell’utente e la sua password tramite uno script PHP; questi dati sono archiviati in un database My SQL. Lo script di autenticazione dell’utente è costituito da due file: uno è il form di
login in html (form.html in fig.1), l’altro (login.php in fig. 2) verifica che i dati inseriti dall’utente con il form si trovino corri-
<form action='login.php' method='post'>
Username: <input type='text' name='user' />
Password: <input type='password' name='pwd' />
<input type='submit' value='Login' />
</form>
Fig. 1 - Istruzioni nel file form.html (Fonte: Wikipedia)
<?php
//Prepara la query in una variabile
$query = "SELECT * FROM users WHERE
user='".$_POST['user']."' AND
pwd='".$_POST['pwd']."'";
//Esegue la query (supponiamo che sia già aperta
una connessione valida al database e $db è lo stato)
$sql = mysql_query($query,$db);
//Conta il numero di righe trovate (se questo numero
è maggiore di 0 i dati immessi sono corretti)
if(mysql_affected_rows($sql)>0)
{
//Esegue la convalida dell'autenticazione e permette
l'accesso a pagine protette
}
?>
Fig. 2 - Istruzioni nel file login.php (Fonte: Wikipedia)
spondano a quelli nel database degli accessi in SQL. Si noti
che in questo file c’è l’istruzione SQL <select> per cercare i dati
nel database.
L’utente da browser compila nel form i due campi <Username> e <Password> che vengono passati a login.php nelle
variabili <$_POST[‘user’]> e <$_POST[‘pwd’]>. L’attacco
SQLIA consiste nell’inserire nello script PHP dati arbitrari tramite
il form in HTML, nell’ipotesi che lo script non compia i dovuti
controlli sui caratteri di <Username> e <Password>, e si possano sfruttare alcuni caratteri speciali negli operatori. In questo esempio, si supponga che l’attaccante conosca l’identificativo di un utente, ma non la relativa password; egli prova
allora a inserire il nome utente <pippo>, che effettivamente esiste, e come password <’ OR user=’pippo>. La combinazione
dei dati inseriti nel form con lo script in php senza specifici controlli porta a creare un’interrogazione SQL come: <SELECT *
FROM users WHERE USER=’pippo’ AND pwd=’’ OR
USER=’pippo’>.
La disgiunzione inclusiva OR restituisce TRUE se una delle due
condizioni è vera. La condizione per l’utente <pippo> è verificata e quindi il login va a buon fine, pur non conoscendo la
password. Anche se non si conosce il nome corretto di un
utente, l’attaccante può provare a settare con operatori speciali quali:
<’ or ‘1’=’1> <’ or ‘1’=’1’ — ‘> <’ or ‘1’=’1’ ({ ‘> <’ or
‘1’=’1’ /* ‘>
L’istruzione SQL diviene
<SELECT * FROM `users` WHERE `name` = ‘’ OR ‘1’=’1’;> <SELECT * FROM `users` WHERE `name` = ‘’ OR ‘1’=’1’ — ‘;>
ed essendo sempre vero che 1=1, l’attaccante effettua l’accesso pur non conoscendo né il nome di un utente né la sua
password. L’esempio mostrato è semplice e serve a capire la
logica dell’attacco con il presupposto che lo script non abbia alcun controllo sui caratteri di input nel form. Si deve tener conto che i più recenti attacchi combinano un SQLIA con
altri tipi di attacco, ad esempio un DoS/DDoS (Denial of Service/Distributed DoS) o un attacco al DNS (Domain Name
System). Per portare un serio SQLIA l’attaccante dovrebbe conoscere la logica dell’applicazione web e di come è strutturato il database SQL. Ma con un poco di pazienza e facendo alcune prove, dotati di un solo browser, si possono
scoprire molte informazioni. Basta ad esempio inserire nel
campo del nome utente della pagina di login di un sito web
un carattere apostrofo, <’>, ed a secondo delle risposte che
si ottengono si può comprendere se l’applicazione è più o
meno attaccabile.
La protezione principale è il controllo dei dati in input da parte
del programma, tenendo conto di tutte le possibili combinazioni
di caratteri speciali e di operatori, e bloccandoli. Per i programmi già in uso è opportuno verificare che questi controlli
ci siano, ed in caso contrario modificare opportunamente il programma. Per la verifica di vulnerabilità tipo SQL injection sono
disponibili sul mercato dei software di verifica (scanning), sia
proprietari che open source. È poi opportuno che i messaggi
con i codici di errore non forniscano, seppur involontariamente,
informazioni preziose per un attaccante… che ci sta provando. È opportuno configurare il sistema in modo che fornisca messaggi d’errore abbastanza generici e senza informazioni di dettaglio. Inoltre è necessario verificare che i privilegi
usati dagli utenti sul database SQL non siano quelli superiori
da amministratore; in caso contrario occorre ridurli. Infine,
come per tutto il software, è indispensabile aggiornare tempestivamente il database server e gli interpreti degli script, soprattutto per eliminare eventuali vulnerabilità.
luglio-agosto 2011
office automation
89