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