INDICE
SPECIALE SQL INJECTION
Difficoltà: INTERMEDIA
• SQL INJECTION (INTRODUZIONE)…………………………….pag.1
• LA TECNICA………………………………………………………..pag.1
• TESTING……………………………………………………………pag.2
• I PROBLEMI PIÙ DIFFUSI………………………………………..pag.3
-
ACCESSI NON DESIDERATI…………………………………………………………pag.3
-
VISUALIZZARE DATI NON ACCESSIBILI………………………………………….pag.4
-
ANALISI DELLE QUERY TRAMITE L’INTRODUZIONE DI ERRORI……………pag.5
-
ADVANCED SELECT INJECTION……………………………………………………pag.5
-
INSERT INJECTION……………………………………………………………………pag.6
-
STORED PROCEDURES INJECTION……………………………………………….pag.7
-
LE FEATURE E I PROBLEMI DEI DBMS PIÙ DIFFUSI……………………………pag.8
• SCRIVERE CODICE SICURO…………………………………….pag.8
• COME PREVENIRE LE SQL INJECTION……………………….pag.9
• CONCLUSIONI………………………………………………………pag.11
SQL INJECTION (INTRODUZIONE)
Negli ultimi due anni, gli attacchi contro le applicazioni web sono aumentati a dismisura
attirando, in qualche modo, l’attenzione di tutto il mondo che “gira” intorno alla sicurezza
informatica. La voglia di proteggersi, con il conseguente aumento dei fondi destinati al
“capitolo” sicurezza, è un problema molto sentito da Comandi ed Enti, così come e in
maniera ancora più maniacale da quei siti web che appartengono ad agenzie o a semplici
industrie dove la tutela del segreto rientra nella lista delle priorità. Il compito del “system
administrator” e di conseguenza del “web master” diventa sempre più un compito difficile
da svolgere senza incorrere in qualche “svista” progettuale la quale potrebbe causare una
falla nel sistema e diventare m un problema di cui se ne può ignorare l’esistenza. La
parvenza di sicurezza pubblicizzata da molte case specializzate nel settore, porta molte
volte ad “hardenizzare” (mettere in sicurezza) solo alcuni aspetti del sistema,
tralasciandone altri, uno di questi riguarda la protezione dei database relativi ai siti web.
L’evoluzione delle esigenze del pubblico “internauta” (neologismo per indicare un utente di
INTERNET) ha comportato l’introduzione di tecnologie dinamiche, tra le quali la creazione
di contenuti “on demand”, ma sono ancora più disparati i servizi offerti al giorno d’oggi dai
siti web. Sono in forte aumento i server, che, anche a livello gratuito, offrono la possibilità
di elaborare script per la creazione di contenuti web, senza dimenticare l’indiscusso
aumento degli utenti che stanno provvedendo a trasformare i propri siti statici in vere e
proprie applicazioni residenti sul web (siti dinamici). Nelle maggior parte dei casi, queste
applicazioni, utilizzano dati provenienti dall’ utente ed introducono quindi la possibilità di
poter modificare delle variabili utilizzate dallo script, aumentando di conseguenza
l’insorgere di vulnerabilità manipolabili da remoto. Nei prossimi paragrafi proveremo ad
analizzare una delle vulnerabilità più diffuse tra le applicazioni “web-related” la SQL
Injection.
LA TECNICA
La maggior parte delle applicazioni web vengono realizzate interfacciando l’applicazione
ad un server DBMS (Data Base Management System) ed interagiscono con tali server con
l’ausilio del linguaggio standard SQL. SQL injection può considerarsi una tecnica di
exploiting delle web application che utilizzano dati provenienti dai client nelle query, senza
controllare la presenza di caratteri potenzialmente dannosi. In particolare, la tecnica
dell’SQL injection prevede lo sfruttamento, attraverso stringhe opportunamente manipolate
ed inviate ad un web server con vulnerabilità specifiche riscontrate nei database SQL.
Contrariamente a quello che si potrebbe pensare, la diffusione di queste vulnerabilità
risulta molto diffusa ed è dovuta in molti casi alla mancanza di professionalità di molti
programmatori, in alcuni casi improvvisati e mancanti di solide basi di programmazione.
Nonostante sia “abbastanza semplice” difendersi da un attacco portato con questa tecnica
ad oggi molte aziende, multinazionali comprese, sono vulnerabili all’attacco e di
conseguenza esposte a danni potenzialmente gravosi dal punto di vista economico e
dell’immagine. In ambito difesa, i danni che potrebbero creare questo tipo di vulnerabilità,
oltre a danni che riguardano l’immagine, potrebbe dar luogo a fuga di notizie con tutte le
1
conseguenze che comporterebbe tale azione. La quasi totalità dei portali a contenuto
dinamico presenti su internet si basa su un colloquio tra web server ed un database SQL.
Il colloquio avviene attraverso le cosiddette query, ovvero le richieste al database, scritte
codificandole attraverso degli URL generati dall'applicazione web. Le query devono
rispettare un certo standard di sintassi, comprendendo stringhe alfanumeriche e
contenenti anche punteggiatura. A livello internazionale il codice ASCII regolamenta la
codifica di tutti i caratteri, in pratica, ogni carattere e' associato ad un valore numerico in
base ad una tabella, ma nel caso delle query SQL generate da un'applicazione web, il
codice ASCII viene sostituito dall'Unicode, che prevede di associare un valore
esadecimale preceduto da un segno % ad ogni lettera o numero che si utilizza. Secondo il
codice Unicode, per esempio, il segno percentuale viene codificato con %25 mentre il
punto si codifica come %2E.
Quando un'applicazione web genera una query SQL dinamica la genera codificandola in
Unicode e, dato che i portali web usano molto spesso gli stessi script per effettuare le
stesse operazioni di gestione, è possibile, per un hacker che sa com'e' strutturato un
determinato script, inserire nella barra di indirizzi di Internet Explorer o qualsiasi altro
browser, una URL contenente una query SQL creata ad hoc che ha come unico scopo
quello di arrecare un danno al web server e all'applicazione che risiede sul server.
Gli attacchi portati con questa tecnica producono due effetti principali: il primo e' quello di
poter inserire ed estrarre dati nel database a piacimento e, nei casi più gravi, quello di
poter ottenere il controllo remoto del server, ovvero di impadronirsi di tutte le sue
funzionalità, con tutto quello che ne consegue a livello di danno aziendale.
Un amministratore di rete che vuole difendersi da un attacco di questo tipo deve testare
tutti gli script che fanno parte dell'applicativo che gestisce, verificando che tutti siano
immuni dall'attacco. Nel prossimo paragrafo analizzeremo alcuni semplici test che un buon
programmatore dovrebbe effettuare per mettere in sicurezza il proprio database; in rete
comunque, sono disponibili white paper su come testare i propri script e su come metterli
in sicurezza, ovviamente è d'obbligo disporre di conoscenze specifiche nel campo dei
database relazionali per poter condurre un'attività specifica di bonifica delle vulnerabilità.
TESTING
In questo paragrafo illustreremo alcuni semplici test che serviranno a controllare le
applicazioni e trovare eventualmente, vulnerabilità dovute alla tecnica dell’SQL Injection.
Questi controlli potrebbero essere molto complessi ma esistono dei casi in cui, la ricerca di
script potenzialmente vulnerabili è molto semplice.
Il test più semplice da effettuare consiste nell’aggiunta di un apice in un form, per vedere
come si comporta nella risposta, il server DBMS; se quest’ultimo, ad esempio, risponde
con una pagina bianca o piena di errori la nostra ricerca della vulnerabilità è già ad un
buon punto. Un buon programmatore dovrebbe avere sotto controllo l’input di ogni
variabile senza dare per scontato che l’utente, utilizzatore della web application, formatti
correttamente le variabili. Ogni possibile campo deve essere testato per tutte le
vulnerabilità per le quali queste potrebbero essere coinvolte, in modo da evitare
ripercussioni in tutto lo script, spesso legato ad altri.
2
Un buon metodo di controllo delle applicazioni web potrebbe essere quello di inserire in
ogni campo una comando tipico di SQL preceduto da un apice, cercando cosi` eventuali
problemi sulle singole variabili. Dopo aver provato i campi uno alla volta potrebbe essere
utile riempire il form con dati formalmente corretti e ripetere la procedura
"apice+comando" per ogni campo, mantenendo formalmente corretti gli altri campi.
Ipotizziamo di passare ad uno script questi parametri formalmente corretti:
script.php?nome=mario&cognome=rossi&[email protected]
Lo script funziona alla perfezione. Proviamo ora a modificare la stringa con un apice nel
parametro "nome":
script.php?nome='mario&cognome=rossi&[email protected]
Ipotizzando che lo script sia vulnerabile, siamo andati a modificare i parametri inviati al
server DBMS dalla query, modificandone strutturalmente la sintassi (ricordo che l'apice (')
e` un operatore SQL).
Cosa potrebbe accadere utilizzando una stringa di parametri come quella proposta
dall'esempio?
I risultati potrebbero essere molteplici: dalla semplice pagina bianca ai piu` disparati errori
provenienti dal server DBMS. Potrebbe riportare l'errore che gli altri paramentri non sono
stati inseriti o addirittura mostrare dati che non dovrebbero essere visualizzati con quella
query. Dopo aver trovato una possibile vulnerabilita` del tipo SQL Injection, la parte piu`
importante e` l'interpretazione degli errori. Se l'errore viene generato del server DBMS
siamo sicuramente davanti ad una vulnerabilita` ad SQL Injection ma gli errori spesso
sono tutt'altro che ovvi. Bisogna inoltre prestare attenzione alle piu` minime modifiche della
pagina, segno di SQL Injection Exploiting, poiche` dei malintenzionati potrebbero
nascondere codice malevole inserendo, ad esempio, eventuali errori negli header del
documento HTML e non mostrandone traccia nel body, (la parte visualizzata dal browser).
Non bisogna fermarsi all'analisi della singola pagina colpita da SQL Injection ma e` buona
abitudine seguire i link presenti nella pagina, alla ricerca di eventuali ripercussioni
sull'intera applicazione ed e` importante seguire anche eventuali “redirect” verso una
pagina di errore predefinita, spesso preceduta da una schermata di errore propria del
database.
I PROBLEMI PIU` DIFFUSI
Passiamo ora all'analisi dei piu` diffusi problemi di sicurezza dovuti alla vulnerabilita` da
SQL Injection.
ACCESSI NON DESIDERATI
L'autenticazione delle web application e` spesso delegata ad uno script di login che ha il
compito di processare la coppia login/password proveniente dal client e di confrontarla con
le coppie presenti nel database. In caso di corrispondenza lo script settera` gli appositi flag
per consentire il nostro accesso o, nel caso opposto, ci vietera` l'accesso.
Consideriamo il seguente codice PHP:
$user = $_GET['nome'];
3
$passwd = $_GET['password'];
$query = mysql_query(“SELECT * FROM utenti WHERE user='$user' AND
password='$passwd'”);
if (mysql_num_rows($query) == 0) {
$logged = 0;
} else {
$logged = 1;
}
Questo breve script prende i dati dalla querystring e li mette nella query senza controllare
la presenza di eventuali caratteri pericolosi. Ipotizziamo di modificare entrambi gli
argomenti passati allo script in "' OR ''='" e di far processare la pagina al server. La parte
condizionale della query passata al server DBMS (in questo caso MySQL) diventa:
... WHERE user='' OR ''='' AND passwd='' OR ''=''
Come si può ben capire, entrambe queste condizioni sono sempre verificate e
mysql_num_rows() restituira` un valore sicuramente diverso da zero (se la tabella contiene
dati) consentendo così il login a qualsiasi persona a conoscenza di questo problema.
VISUALIZZARE DATI NON ACCESSIBILI
Il mancato parsing (controllo/analisi) dei parametri per caratteri maligni ha introdotto la
possibilita` di editare, a piacimento
dell'attaccante, la query verso il database. Abbiamo appena visto che e` possibile entrare
con il massimo dei
privilegi in un'applicazione web ma si potrebbe decidere di accedere a dati non
direttamente accessibili dall'applicazione stessa. Lo standard SQL permette la creazione
di “SELECT” multiple tramite il comando “UNION” e tale comando puo` essere sfruttato
per gli scopi dell'attaccante.
Prendiamo in esame la seguente query:
“SELECT nome FROM users WHERE paese='$var'”
La variabile $var dovrebbe contenere il paese di provenienza degli utenti, dei quali stiamo
cercando il nome ma, su di essa, non viene fatto nessun controllo ed e` quindi possibile
scrivere codice SQL direttamente nella variabile.
Nel nostro caso $var conterra`
' UNION ALL SELECT nome, passwd FROM users ''='
Vediamo il contenuto della query una volta settata $var:
SELECT nome FROM users WHERE paese='' UNION ALL
4
SELECT nome, passwd FROM users WHERE ''=''
Evidentemente la prima SELECT non restituira` nessun record (supponendo che nessun
utente ha il campo paese vuoto) mentre la seconda SELECT e` incondizionata e restituira`
tutte le coppie nome/password.
Il problema e` quello della visualizzazione dei dati: i dati ora sono stati estratti dal
database ma l'applicazione considera solo il campo "nome" e non "password". Un fattore
mitigante consiste nel fatto che il linguaggio SQL permette l'aliasing dei campi tramite il
comando AS che puo` essere sfruttato per fare l'output dei dati non visualizzabili
ordinariamente.
ANALISI DELLE QUERY TRAMITE L'INTRODUZIONE DI ERRORI
Molti server web restituiscono parte delle query in caso di errore. Normalmente questa
funzionalita` e` utile, anzi, in alcuni casi necessaria, durante il debugging delle applicazioni
web, ma puo` essere usata impropriamente per analizzare le query e di conseguenza
carpire informazioni sulla realizzazione di una web application vulnerabile da SQL
Injection.
Quindi, risulterebbe utile testare un'applicazione inserendo volutamente errori di sintassi
nei campi che interagiscono con l'utente, magari utilizzando costrutti SQL incompleti come
"valore' ", " ' ", "'valore", " ' OR ' ", ";" e "0,1,2".
ADVANCED SELECT INJECTION
Non sempre le web application elaborano query semplici e lineari. Capita a volte che siano
presenti istruzioni racchiuse da parentesi, selezione sulla base di wildcards e campi non
direttamente modificabili.
Iniettare codice sintatticamente corretto e funzionante all'interno di queste tipologie di
query potrebbe richiedere l'utilizzo di piccoli accorgimenti, a volte non immediati.
SELECT nome FROM utenti WHERE (paese='campovariabile')
Estrapolare dati da una query di questo tipo non puo` essere fatto con il metodo visto nelle
pagine precedenti poiche` ci verrebbero segnalati diversi errori di sintassi. Occorre quindi
modificare la query utilizzando un campo di questo genere:
') UNION ALL SELECT campo FROM altraTabella WHERE (''='
che, sostituita nella precedente, soddisfa perfettamente la sintassi SQL:
SELECT nome FROM utenti WHERE (paese='') UNION
ALL SELECT campo FROM altraTabella WHERE (''='')
5
Altra sintassi che potrebbe creare problemi e` quella dovuta al costrutto di confronto LIKE.
SELECT nome FROM utenti WHERE nome LIKE '%campovariabile%'
I simboli di percentuale funzionano nelle query SQL come wildcards e un eventuale
completamento %% ritornerebbe tutti i record e quindi non sarebbe applicabile il costrutto
UNION.
Bisogna quindi pensare ad inserire una stringa che non risulti in nessuno dei record, come
potrebbe essere ad esempio "!?!".
Un campo tipico per iniettare codice in questa query potrebbe essere il seguente:
!?!%' UNION ALL SELECT campo FROM tab WHERE campo LIKE '%
Sostituendo la query SQL diventa:
SELECT nome FROM utenti WHERE nome LIKE '%!?!%'
UNION ALL SELECT campo FROM altraTabella
WHERE campo LIKE '%%'
INSERT INJECTION
Finora abbiamo considerato SQL Injection un problema legato al costrutto SELECT ma
possiamo tranquillamente dire che questa vulnerabilita` si puo` estendere a qualsiasi
query contentente input dell'utente non appositamente controllato. Un altro costrutto
potenzialmente vulnerabile e` INSERT, necessario per l'inserimento di nuovi record
all'interno di una tabella. Iniettare codice nella query INSERT consente all'utente
smaliziato di prelevare dati da un database e utilizzarli per la propria registrazione. Ad
esempio e` possibile registrarsi al posto di un altro utente senza aver nessun dato su di lui.
L'unico “trucco” necessario per assicurarsi dell'effettiva estrazione dei dati e` quella di
visualizzarli (ad esempio tramite il pannello di controllo).
Per portare a termine questo tipo di exploit il server DBMS deve supportare le
SUBSELECT (ad esempio MySQL non supporta questa feature) e si devono conoscere i
nomi di campi e tabella, ricavabili con un po' di reverse engineering.
Ipotizziamo di avere la seguente query di inserimento:
INSERT INTO tab (nome, cognome) VALUES ('campo1', 'campo2')
Se al posto di campo1 inseriamo
' + SELECT nome FROM tab LIMIT 1 + '
e al posto di campo2 inseriamo
' + SELECT cognome FROM tab LIMIT 1 + '
6
otteniamo una perfetta replica di un record esistente all'interno del database poiche` la
query in questione diventa:
INSERT INTO tab (nome, cognome) VALUES ('' +
SELECT nome FROM tab LIMIT 1 + '', '' + SELECT cognome FROM tab LIMIT
1 + '')
Per cambiare l'utente da selezionare basta scorrere i record con l'offset offerto
dall'istruzione LIMIT o, eventualmente, usare la sintassi NOT IN () per “ciclare” i record.
STORED PROCEDURES INJECTION
Sfruttare le “stored procedures” e` generalmente molto piu` semplice che agire sul
costrutto SELECT.
Le stored procedures sono parti di codice SQL richiamabili nei costrutti SQL tramite
l'utilizzo di EXEC e sono praticamente degli script batch, atti ad effettuare operazioni
direttamente all'interno del server DBMS.
Questi, hanno la particolarita` di essere abbastanza veloci e sono molto utilizzati per le
operazioni transizionali.
Non tutti i server DBMS permettono l'esecuzione delle stored procedures e, per richiamare
l'esecuzione delle stesse, e` necessario che lo stesso server permetta l'utilizzo di
statement multipli (istruzioni SQL distinte separate da un punto e virgola). Diversi server
DBMS hanno, comunque, queste feature e possiedono, inoltre, diverse Stored Procedures
predefinite, molte delle quali possono compiere operazioni molto interessanti per un
attaccante. Esaminiamo la vulnerabilita` piu` evidente nel server DBMS di MicroSoft, MS
SQL Server. Tale server attiva di default innumerevoli stored procedures, fra le quali
troviamo xp_cmdshell ovvero un frontend per l'interprete dei comandi dei sistemi basati
su kernel NT. Il server in questione supporta statement multipli e basta quindi una
qualsiasi vulnerabilita` da SQL Injection per accedere al sistema con i permessi del server
SQL.
Consideriamo la seguente query:
SELECT * FROM tab WHERE nome='campovariabile'
Terminando il primo costrutto con un nome arbitrario ed applicando la sintassi di EXEC
sulla procedura xp_cmdshell otteniamo la sequente query:
SELECT * FROM tab WHERE nome='ed'; EXEC
master.dbo.xp_cmdshell 'cmd.exe comando'
Al posto di "comando" possiamo immettere qualsiasi stringa di comando interpretabile
dalla shell dei sistemi NT, ovvero il sistema e` in balia dei comandi arbitrari. Ovviamente il
sistema server SQL di Microsoft non e` l'unico ad offrire stored procedures predefinite ma
7
e` stato preso in considerazione per la gravita` della situazione che, combinata con errori
di programmazione web permette l'accesso ad utenti non desiderati.
E' quindi bene disabilitare, o rimuovere, le stored procedures non necessarie al corretto
funzionamento del server e assicurarsi che i permessi sulle parti vitali del sistema siano
piu` restrittivi possibile.
LE FEATURE E I PROBLEMI DEI DBMS PIU` DIFFUSI
MySQL
Supporta 'INTO OUTFILE'
Supporta 'UNION' (dalla versione 4.x)
Spesso gira come "root"
Molti moduli e librerie non supportano statement multipli
Oracle
Supporta le SubSelect
Supporta 'UNION'
Supporta le stored procedures
Non supporta statement multipli
Molte stored procedures preimpostate, alcune delle quali pericolose
DB2
Supporta le SubSelect
Supporta 'UNION'
Supporta le stored procedures
Non supporta statement multipli
Postgres
Supporta 'COPY' se fatto girare come superutente
Supporta le SubSelect
Supporta 'UNION'
Supporta le stored procedures
Supporta gli statement multipli
MS SQL Server
Supporta le SubSelect
Supporta 'UNION'
Supporta le stored procedures
Supporta gli statement multipli
Molte store procedures preimpostate sono pericolose
SCRIVERE CODICE SICURO
Come già accennato nei paragrafi precedenti ogni web application che si rispetti, deve
seguire piccole norme di programmazione per elevare la sicurezza al massimo. Se
l'applicazione riceve input dall'utente questo deve essere processato appropriatamente in
modo da escludere eventuali caratteri maligni, che potrebbero interferire con le query
previste dai programmatori. E' quindi necessario lasciar passare solo i caratteri necessari
8
e filtrare tutti gli indesiderati tramite l'utilizzo di parser appositi (magari una regular
expression ben congegnata). Ad esempio per lasciar passare solo i caratteri alfabetici la
regexp (regular expression) seguente e` l'ideale:
s/[^a-zA-Z]//g
mentre per far passare i soli numeri si puo` applicare:
s/[^0-9]//g
Lasciare solo i caratteri alfanumerici e` quasi sempre un'ottima soluzione al nostro
problema ma puo` capitare di aver bisogno di altri tipi di caratteri. In questo caso e` bene
sostituire ai caratteri la loro codifica nello standard UniCode o nello standard HTML.
Ovviamente e` sempre bene utilizzare il minimo numero possibile di caratteri non
alfanumerici per evitare potenziali problemi di iniezione. Altra feature interessante per
aumentare la sicurezza delle web application potrebbe essere l'individuazione di tentativi
di iniezione del codice prima del passaggio a stored procedures e a query. All'interno delle
stored procedures e` bene non creare le query dinamicamente ma cercare di mantenere
fisso piu` codice possibile. Realizzare una procedura di questo tipo richiede la creazione di
una procedura contenente la sola query statica ed il semplice passaggio delle variabili
come parametri.
Ad esempio:
CREATE PROC
usr_prendiUtenteDaNick
@nick nvarchar(255)
AS
SELECT nome, cognome, indirizzo, telefono
FROM utenti
WHERE nick = @nick
RETURN
La configurazione del server deve essere piu` restrittiva possibile e deve evitare la
possibilita` di accedere liberamente a parti del sistema non normalmente disponibili.
Disabilitare le stored procedure non necessarie agli utenti potrebbe essere la soluzione ai
nostri problemi ma un'attenta policy di permessi potrebbe evitare la mutilazione eccessiva
del server DBMS.
COME PREVENIRE LE SQL INJECTION
Prevenire le SQL injection è un compito relativamente semplice ed è possibile svolgerlo in
vari modi a seconda dei casi e delle preferenze. Analizziamo ora, una per una, tutte le
possibilità per proteggere la propria applicazione web (nel nostro caso PHP) dalle SQL
injection. Una prima soluzione ci è fornita direttamente dal file di configurazione php.ini .
Impostando la voce magic_quotes_gpc PHP si prenderà cura di aggiungere i caratteri di
9
escare davanti a tutti gli “ ‘ “ (apice) contenuti nei Cookie, Post e Get. Questa soluzione
non è tuttavia ottimale in quanto potrebbe causare incompatibilità con molte applicazioni
web di terze parti ed inoltre non protegge da input “maliziosi” non provenienti da cookie,
Post o Get ed in applicazioni particolarmente complesse non è impossibile che, studiando
l’applicazione, un hacker possa trovare il modo per poter infiltrare da qualche parte la sua
SQL injection.
Una seconda soluzione è quella di utilizzare addslashes() o funzioni simili come
mysql_escape_string() su tute le variabili inserite in una query SQL. In questo modo si
sarà sempre sicuri che in tutti i valori passati gli apici verranno convertiti in \’ rendendoli
così inoffensivi. Si noti però, come questa precauzione, così come quella precedente,
diventa realmente sicura, solo se, nelle query SQL si utilizza l’apice anche quando si
manipolano valori numerici. In tutte le query è infatti consigliabile utilizzare sempre sintassi
del tipo id=’1’ . In questo caso saremo protetti dalle SQL injection, in caso contrario un
hacker potrebbe comunque aggiungere un OR 1=1 dopo l’id desiderato senza che il
nostro addslashes() possa in alcun modo aiutarci.
Il problema non è limitato comunque al solo uso degli apici ma si presenta allo stesso
modo usando come delimitatore di stringa nelle query il carattere “ (virgolette).
Fortunatamente mysql_escape_string() effettua l’escape di tutti i caratteri che possono
essere usati come delimitatori di stringa risolvendo parecchi problemi.
Un’ultima alternativa, che risulta la più complessa, ma anche la più sicura, è quella di
controllare di volta in volta ogni variabile inserita in una query con regular expression o
altre funzioni specifiche. Se per esempio sappiamo a priori che una variabile deve
contenere un numero intero potremmo usare una soluzione di questo tipo:
$id = (int)$_POST[“id”];
$query=mysql_query(“SELECT * FROM users WHERE id=$id”,$DB);
I questo caso possiamo essere sicuri che il campo id sarà un campo numerico, se
qualcuno provasse ad inserire valori di altra natura la sintassi (int) restituirebbe infatti
valore 0. In questo caso è persino inutile utilizzare gli apici prima e dopo $id.
Nel caso invece di output testuali o di altra natura non numerica la soluzione ideale sono
senza ombra di dubbio le regular expression, create di volta in volta per accettare
esclusivamente il tipo di dati che si prevede utilizzare.
Se ad esempio si desidera filtrare una variabile $stringa per essere sicuri che contenga
solo caratteri alfanumerici si può usare la seguente regular expression:
if (ereg(“^[A-Z0-9]+$”,$stringa)) {
mysql_query(“SELECT * FROM users WHERE nome=$stringa’ ”,$DB);
} else print ‘Parametro non valido’;
Le Regular Expression sono senza ombra di dubbio lo strumento più potente a
disposizione dei programmatori PHP per verificare che ogni input dell’utente, qualsiasi sia
la sua provenienza, corrisponda effettivamente al tipo di dato che era stato richiesto.
10
Questo tipo di controllo è sicuramente più complesso rispetto agli altri due o ad altri che
potrebbero venir utilizzati ma garantisce, se la regular expression è ben strutturata, una
sicurezza estremamente elevata: se un campo della nostra applicazione deve contenere
solo ad es. : “mele”, è sempre meglio verificare che contenga effettivamente mele piuttosto
che controllare che non contenga pere, in questo secondo caso infatti, anche in assenza
di pere, il campo potrebbe comunque contenere pesche o altro. Questo semplice esempio
dovrebbe rendere l’idea di quello che idealmente bisognerebbe realizzare per ogni
parametro. Ciò è per altro consigliabile non solo per prevenire possibili SQL injection ma
anche altri tipi di attacchi o comunque spiacevoli bug ed errori imprevisti durante l’utilizzo
dell’applicazione da parte degli utenti.
Qualunque sia la tecnica preferita, l’importante è implementare sempre almeno uno dei
metodi di prevenzione qui descritti. Le SQL injection, come già detto, sono un tipo di
attacco estremamente facile da eseguire per chiunque abbia un minimo di conoscenze su
PHP e database ed i risultati di un simile attacco possono risultare gravi.
CONCLUSIONI
Abbiamo visto nei precedenti paragrafi, come un non corretto sviluppo applicativo, possa
permettere potenzialmente ad un malintenzionato di effettuare un attacco al database
tramite la immissione di caratteri “anomali” in una query al database. Allo stesso tempo,
tale “vulnerabilità può tra l’altro facilmente essere ovviata adottando le seguenti
precauzioni:
- utilizzare dei valori predefiniti per sostituire gli input non congrui;
- predisporre un messaggio di errore alla ricezione di query irregolari;
- costruire un sistema di logging che registri tutti i tentativi di intrusione.
Indipendentemente dal tipo di difesa che si decide di intraprendere, il fattore comune che
ogni programmatore deve tener presente e che ogni input deve essere controllato prima di
arrivare sul database.
11