Abbiamo tutti funzionalità di ricerca o login nelle nostre applicazioni. Ma sei sicuro che le funzionalità stiano facendo esattamente quello che dovrebbero fare?
Oggi parleremo di come il “carattere jolly” % e l’operatore “LIKE” possano bypassare importanti controlli nella tua WebApp con l’aiuto dell’ultimo laboratorio PMS rilasciato da @h4t4way.

Nel caso volessi prima avere una overview sul funzionamento delle SQL Injection ti rimando al precedente articolo SQL Injection – Introduction – Pentesting Made Simple.
Tutte le live riguardanti il mondo del Pentesting e BugBounty potete trovarle sui nostri canali social Twitch e Youtube.

Wildcards e operatore LIKE!

Nel linguaggio SQL l’operatore di confronto LIKE permette di analizzare il contenuto parziale di una stringa e viene usato nella condizione WHERE delle interrogazioni SELECT.
L’operatore LIKE utilizza due caratteri speciali (chiamati anche caratteri jolly o wildcards) da inserire dentro le stringhe da comparare: la percentuale (%), che sostituisce un insieme di caratteri in una stringa e l’underscore (_) che sostituisce un singolo carattere nella stringa.

Per esempio, con l’operatore di confronto LIKE e la stringa “Mo%y” si possono selezionare tutte le parole (di qualsiasi lunghezza) che iniziano con “Mo” e finiscono per “y”.
Invece con l’operatore “_” la stringa “Monk_ys” si possono selezionare tutte le parole di 7 lettere che iniziano per “Monk” e finiscono per “ys”.

La sintassi per usare una SELECT / LIKE è la seguente:

SELECT [colonne] FROM [tabella] WHERE [colonna LIKE stringa]

Quindi un esempio pratico di query SQL adattata agli esempi precedenti potrebbe essere:

SELECT nome, cognome FROM users WHERE team LIKE 'Mo%s'

Wildcards injection in query SQL!

Dopo aver compreso la teoria passiamo al vero attacco. Immaginiamo di avere un endpoint di questo genere:
https://pms.net/vulnerable.php?param=test
Se la query nel backend fosse del tipo:
SELECT text FROM table WHERE colonna LIKE '$param'
potremmo tranquillamente enumerare ogni valore del parametro param con la sintassi
https://pms.net/vulnerable.php?param=a%
https://pms.net/vulnerable.php?param=b%
e così via…

Ma in quali situazioni questo comportamento può rivelarsi davvero dannoso?

  • Login form, dove è possibile trovare questa vulnerabilità nei campi username e password.
  • Nei form di password recovery, e far in modo di resettare la password di altri utenti registrati.
  • Nei campi contenenti identificatori di sessione o token. Questa vulnerabilità può permetterci di “rubare” o “prevedere” i token o gli ID di sessione di altri utenti.
    Esempio: http://www.example.com/admin/privado.php?sessionid=1_________
    In questo caso possiamo avvalerci del carattere “_” sapendo a priori la lunghezza del sessionid.

Da notare che l’iniezione del carattere jolly % a volte può essere difficile, perché questo carattere viene solitamente filtrato per evitare attacchi di codifica o proprio perché è erroneamente decodificato (in questo caso possiamo sostituirlo con %25 o %2525).

La domanda sorge spontanea, perchè i programmatori sbagliano?
Sicuramente se l’applicazione è completamente custom è possibile incorrere in errori di distrazione ma in passato è stato evidenziato che frameworks come Django o in moduli di Symfony come Propel sono stati riscontrati errori molto simili.

La seguente sintassi di Django:
result=Entry.objects.get(text__contains='PMS')
portava ad una query di questo genere:
SELECT colonne WHERE text LIKE '%PMS%'

Reference: [Propel Login] Login with * or % · Issue #1688 · FriendsOfSymfony/FOSUserBundle (github.com)

Laboratorio PMS!

È possibile raggiungere il laboratorio a questo link .
Il creatore ha costruito una login page vulnerabile ai tipi di attacco appena descritti.

Sappiamo che la query che gira nel backend è la seguente:

$username = $_POST['username'];
    $password = $_POST['password'];

    $hostname = $_SERVER['HTTP_HOST'];

    $query = sprintf('SELECT username FROM member WHERE username LIKE "%s" AND password LIKE "%s" LIMIT 1;', mysql_real_escape_string($username), mysql_real_escape_string($password));

    $res = ssql_value($query);

Proviamo ad inserire un classico admin admin e vediamo cosa risponde la WebApp.

Possiamo “greppare” per keyword “wrong” e notiamo che non abbiamo ottenuto accesso alla WebApp.

Come spiegato in precedenza ed avendo avuto accesso al codice sorgente possiamo dedurre che il carattere jolly % può aiutarci a bypassare il login form. Proviamo…

Vediamo infatti che in questo modo è possibile accedere al pannello dell’utente admin.
Possiamo andare su “show response in browser” (click destro sulla tab Response) e incollare l’url nel browser.

Notiamo subito che siamo riusciti ad accedere alla dashboard dell’utente admin.

È possibile giocare con la logica dei caratteri jolly in molteplici modi, tu riesci a trovare un’altra soluzione per bypassare il login form o trovare la password esatta dell’admin?
Faccelo sapere sui nostri canali social di Telegram e Discord!

Donato Di Pasquale
Donato Di Pasquale
@dipa996 | linkedin.com/in/ddipa | dipa.undo.it

Lascia un commento