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