SQL INJECTION --- SICUREZZA
.:luxx:.
PREMESSE
Questa guida accenna ad alcuni metodi di SQL injection e si
sofferma sulla prevenzione di tali attacchi, per comprendere al
meglio il testo è necessaria una conoscenza di base del linguaggio
SQL.
INTRODUZIONE
Lo Structured Query Language, meglio conosciuto come SQL, è
quel linguaggio usato per la gestione di strutture database, quindi
viene gestito da linguaggi di programmazione per pagine web
dinamiche come PHP e ASP.
L'SQL injection è una tecnica usata in certi attacchi web, dove si
mira a colpire il database di un sito, o a riuscire ad ottenere
informazioni su di esso sfruttando delle vulnerabilità che vedremo
nel corso della guida.
Di tipologie di database ne esistono diverse, ognuna con le sue
pecche, tra i tanti è bene conoscere MS SQL Server, che a causa
della sua compatibilità con certi comandi è considerato il più
vulnerabile, Oracle e MySQL(considerato il meno vulnerabile).
L'attacco vero e proprio consiste nel riuscire a far passare alla
pagina dinamica particolari query, interrogazioni, che poi invieranno
una certa richiesta al database.
METODI D'INTRUSIONE
L'attacco avviene principalmente attraverso aree di input dell'utente
o tramite url, a seconda che si abbiano diversi metodi della pagina
dinamica di passare i valori al database.
L'utente, ad esempio, potrebbe inserire alcuni caratteri come
l'apostrofo, il doppio trattino, il punto e virgola che hanno un
certo significato in SQL e che potrebbero portare, se utilizzati
correttamente, a risultati diversi.
Immaginiamo ad esempio di avere un modulo di login.
La variabile che prende il valore inserito dalla textbox username la
chiamiamo $username, la variabile della password la chiamiamo
$pass.
Una query mal controllata che gestisce questi dati è una del tipo:
SELECT * from tabella_utenti WHERE username='$username'
AND password='$pass'
In questo caso la query è facilmente modificabile; se si inserisce nel
campo username la stringa prova' OR 1=1-- si ottiene l'accesso
senza aver bisogno di inserire password.
L'apice che inseriamo chiude la reale parte che varrà presa dalla
pagina dinamica di input, ma dopo troviamo OR 1=1, che indica
una condizione che è sempre verificata e che da sempre come
risultato il valore booleano true.
Il doppio trattino, infine indica un commento e serve a rendere
nullo l'ultimo apice.
La query quindi diventa
SELECT * from tabella_utenti WHERE username='prova' OR
1=1--' AND password=''
Di metodi di intrusione ce ne sono diversi, ma ora, iniziamo a
parlare di come prevenirli.
SICUREZZA
Abbiamo già detto che tipologie e metodi di iniezione di codice
SQL ce ne sono diversi, anzi ce ne sono parecchi, quindi non esiste
una vera e propria cura, esistono invece alcune accortezze per
prevenire eventuali attacchi.
La cosa fondamentale è il controllo dell'input inserito dall'utente,
ci serviremo quindi di specifiche funzioni, preferibilmente gestite
lato server, e non da script javascript, per cercare di eliminare, ad
esempio, quei caratteri speciali di cui abbiamo parlato prima.
Altro punto importante è controllare quei messaggi d'errore che
vengono inviati dal server al malintenzionato che cerca di
intrufolarsi nel database, esempio sono i famigerati errori ODBC,
quali avvertono l'utente dell'errore fornendogli “gentilmente” la
parte di codice PHP o ASP interessata dall'errore.
In molti casi, inoltre, le SQL injection si servono di utenti ceh
hanno un certo livello di privilegio nel database, è bene ridurre o
eliminare questa categoria di utenti.
CONTROLLO DEI VALORI
Per eliminare quei caratteri potenzialmente pericolosi dalle nostre
query esistono una serie di funzioni e procedimenti.
Un procedimento comune per contrastare le SQL injection è
l'escape, esso si verifica ad esempio se la direttiva
magic_quotes_gpc del file php.ini è attiva; questa operazione va ad
aggiungere semplicemente un carattere backslash('\') prima di quei
caratteri pericolosi come gli apici singoli o doppi.
magic_quotes_gpc opera sulle variabili passate tramite $_GET,
$_POST e $_COOKIE.
I dati passati alla pagina devono essere inoltre filtrati, ossia devono
subire un controllo sul loro tipo; esempio tipico è il type casting,
che forza una variabile ad essere riconosciuta come un determinato
tipo, è quindi usata se si vuole avere un tipo di dato certo di input.
$valore=(int) $_GET['valore'];
$query=” SELECT * from tabella WHERE input=$valore”;
Ora siamo sicuri che il valore della variabile che viene passata è di
tipo intero.
Una funzione spesso usata per effettuare il type casting è
settype(/*esempio*/$_GET['valore', 'int'];)
Altro metodo per controllare il tipo di valori è usare delle vere e
proprie funzioni di controllo come is_int() oppure gettype().
Spesso è utile filtrare i dati di input attraverso espressioni regolari,
che possono definire, ad esempio, una range di caratteri disponibili
per un login; funzioni che gestiscono questo sono preg_match() e
ereg().
“
E s p r e s s i o n e r e g ol a r e, D a W i k i p e di a , l'e nciclo pe di a
li be r a.
Le espressioni regolari sono sintassi attraverso le quali si possono
rappresentare insiemi di stringhe. Gli insiemi caratterizzabili con
espressioni regolari sono anche detti linguaggi regolari(e coincidono quelli
generabili dalle grammatiche regolari e riconoscibili dagli automi a stati
finiti).
Più rigorosamente possiamo definire un'espressione regolare, a partire da
un alfabeto Σ ed un insieme di simboli {+,*,(,),.,∅} come la stringa R
appartenente a (Σ ∪ {+,*,(,),.,∅})+ tale che valga una delle seguenti
operazioni
1.R = ∅
2.R appartiene a Σ
3.R = S +T oppure R =S T oppure R =S * con S e T sono espressioni
regolari sull'alfabeto Σ
“
In questi casi si può decidere di eliminare i caratteri pericolosi o
semplicemente cambiarli con altri caratteri.
Funzioni che gestiscono queste operazioni sono str_replace(),
preg_replace(), ereg_replace() o strtr().
In precedenza abbiamo parlato dell'escape, gestito dall'attivazione
della direttiva magic_quotes_gpc; bene è da considerare il fatto che
questa operazione non può essere gestita da tutte le tipologie di
server, e sarebbe meglio utilizzare funzioni proprie del database,
come ad esempio mysql_escape_string() o mysql_real_escape
string() per MySQL.
Questi generi di funzioni si possono facilmente reperire sulle
documentazioni delle distribuzioni di database.
Concludo ricordando che questi metodi non hanno un infallibilità
del 100%, ma rimangono comunque delle buone soluzioni per
prevenire questi tipi di attacchi.
.:luxx:.