Come Evitare le SQL Injection

sql-injection

Per Sql-Injection si intendono comunemente tutti quegli attacchi ad un’applicazione, solitamente Web. Tale attacco può essere generato da due fonti di traffico, o tramite FORM o url injection, a seconda di come abbiamo realizzato il nostro applicativo. Il  problema è molto serio infatti la perdita di dati, o il furto degli stessi può compromettere seriamente la stabilità del sistema e della privacy dei nostri utenti, esaminiamo come creare un attacco sql-injection.



Come creare una query mysql injection

Una tipica query che si può testare con questo metodo e quella legata all’ URL-SQL-Injection. Consideriamo un sito che non faccia uso di RewriteEngine, quindi con un url della forma http://sqlattack.injection/attack.php?id=1. L’id visto nell’url è il nostro gancio per lanciare la nostra query di attacco, infatti se l’amministratore non ha apposto eventuali accorgimento posiamo concatenare all’id un frammento di codice sql che ampli la richiesta della query, e anche se in questo caso, molte volte l’sql injection non può farci entrare in dati sensibili o fare danni vari, può aiutarci a farci capire la struttura del db che abbiamo di fronte, un tipico esempio:


http://sqlattack.injection/attack.php?id=1′ OR 1=’1, che sul server può essere vista come


  • normale= SELECT * FROM table WHERE id=’1′
  • con SQL Injection = SELECT * FROM table WHERE id=’1′ OR 1=’1′

In maniera molto più pesante e compromettente l hacker può decidere di giocare duro e sporco, lanciando i suoi assi migliori.A complicarci la vita infatti ci sono le wildcard ovvero i caratteri jolly che si usano sopratutto nelle query di tipo LIKE. Il % rappresenta una wildcard infatti aggiungendo la clausola where campo like ‘%%’ si selezioneranno tutti i fields presenti nel database. In maniera ancora più pesante l’utilizzo del carattere # può essere utile ad un hacker in molte occasioni nel tentativo di sfruttare SQL-Injection per scopi non previsti dall’applicazione, possiamo annullare tutte le regole che seguono l’injection introducendo il carattere #


  • …WHERE campo like ‘%%’ #and campo=val limit 0,25

#and campo=val limit 0,25 non sarà preso in considerazione dalla query

Possiamo comunque consolarci pensando che c’è chi sta molto peggio dei programmatori PHP. La funzione mysql_query infatti non consente l’utilizzo del carattere speciale ; che nel linguaggio SQL indica solitamente il termine di un’istruzione e l’inizio di una nuova. Altri linguaggi di programmazione Web infatti consentono l’uso di questa funzionalità; i rischi sono altissimi. Un hacker potrebbe infatti modificare un SELECT per eseguire qualsiasi altra query come, ad esempio: “ SELECT * FROM users WHERE username=’admin’ AND password=’aaa’; drop table users “. Una simile query cancellerebbe l’intera tabella degli utenti. Questa protezione può comunque venire a mancare nel caso si usino altri database come PostgreSQL, PHP prevede una funzione pg_send_query capace di effettuare più query separate da un ; in un’unica istruzione. L’uso di questa funzione, estremamente raro, è assolutamente deprecabile perché, come illustrato, potrebbe consentire SQL Injection molto pericolose, capaci di eseguire comandi arbitrari sul database.



Come difendersi dalla SQL INJECTION


Prevenire le SQL Injection è un compito relativamente semplice ed è possibile svolgerlo in vari modi a seconda delle proprie preferenze.

Una soluzione è quella di utilizzare addslashes() o funzioni simili come mysql_escape_string() su tutte 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. Questa precauzione, è realmente sicura SOLO se, nelle query SQL si utilizza l’apice anche quando si manipolano valori numerici.

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 risolvendoci molti problemi.

Un alternativa, 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.


  1. Variabile passata di tipo numerico

    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"];


    In 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.


  2. Variabile passata di tipo STRING

    Nel caso invece di input 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 di utilizzare.

    Se ad esempio si desidera filtrare una variabile $stringa per esser sicuri che contenga solo caratteri alfanumerici si può usare la seguente regular expression:

    if (ereg(”^[A-Z0-9]+$”,$stringa)) {

    …query…

    } else exit;


    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.

    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.

    Con questa rapida guida spero che le vostre applicazioni siano molto più sicure, buon lavoro

pdf

Tags: ,

Scritto da Santarelli Luca lunedì, 2nd marzo , 2009 01:45 Letture:

    « File Upload Con le Servlet  |  Il Buon Notaio Diceva… »

    Leave a Reply