Wednesday, February 2, 2011

DVWA: SQLI in BruteForce Easy

Questo post fa parte della serie DVWA.

In questo post non discuterò della vulnerabilità al brute force della pagina (nessun limite di tentativi, nessun controllo anti-bot, link costante, messaggio di errore deterministico...), ma dell'attacco SQL Injection a cui è vulnerabile.

Provando con il classico tentativo (inserendo ' nei due campi), otteniamo un errore:

[...] for the right syntax to use near '3590cb8af0bbb9e78c343b52b93773c9'' at line 1
Quella stringa di caratteri è un hash (più precisamente è il risultato di md5(') ). Da qui possiamo dedurre che le password siano salvate nel database tramite il loro hash. Dunque un attacco sqli al campo password è impossibile (qualunque stringa inserita è convertita in una stringa esadecimale da 32 caratteri). Tuttavia è possibile un attacco al campo username. Proviamo a dedurre la query:

SELECT * FROM tabella WHERE user = '$user' AND password = $password;

Non si può (come negli altri casi) inserire nel campo user il valore 1' OR '1' = '1, poichè la query risultante sarebbe:

SELECT * FROM tabella WHERE user = '1' OR '1' = '1' AND password = $password;

Se la password non è corretta, la query restituisce false.
Per aggirare questa condizione, possiamo usare il commento SQL: --, in modo da costruire questa query (gli spazi sono importanti!):

SELECT * FROM tabella WHERE user = '1' OR 1 -- AND password = $password;

Se il campo user vale "1' OR 1 -- ", otteniamo il risultato desiderato.

La query è corretta, però se proviamo ad inserire questo valore, non riusciamo a effettuare il login. Perché?

Una pratica molto comune nei casi dove il numero di risultati della query è noto, è quella di effettuare il controllo del numero di risultati.
Nel caso del login il risultato della query deve essere uno solo, poichè deve esistere una sola entry per una coppia (user, password).

A questo punto ci viene in aiuto SQL, con il comando LIMIT, che permette di selezionare indice e numero di risultati forniti dalla query. Mettendo in pratica, scrivendo 
 "1' OR 1 LIMIT 0,1 -- ", la query sarà:

SELECT * FROM tabella WHERE user = '1' OR 1 LIMIT 0, 1 -- 'AND password = $password;

Siamo riusciti ad effettuare il login!

C'è un'altra cosa interessante. In caso di succesful login, viene aggiunta alla pagina una immagine che ha come nome ciò che sembrerebbe il nome dell'utente con cui ci siamo loggati (es: admin.jpg). Perciò inserendo nel campo user 
"1' OR 1 LIMIT x,1 -- ", dove x >= 0, possiamo loggarci come ogni utente del sistema e leggerne il nome dall'immagine caricata.

No comments: