Aggirare la sanitizzazione di JavaScript per attacchi XSS in applicazioni Web

Tempo di lettura: 9 minuti
Data pubblicazione: March 9, 2018

Nell’analisi di applicazioni web spesso ci troviamo di fronte a situazioni nuove, mai viste e che necessitano di essere capite per poter identificare la presenza di bug o problemi nel codice del server. In questo articolo andremo a vedere come evadere una serie di filtri JavaScript, il che ci potrà essere utile in diverse situazioni.

Il primo segnale, da parte di un’applicazione web, di una possibile vulnerabilità di tipo XSS (Cross-Site-Scripting), è la presenza, nelle risposte emesse dal server, di stringhe che l’utente genera in input. Per fare un semplice esempio, immaginiamo che l’URL del nostro target sia

http://www.google.com

Se, richiedendo l’URL modificato

http://www.google.com/stringamalevola

l’applicazione inserisce “stringamalevola” in un messaggio di errore che viene mandato a schermo, allora l’applicazione potrebbe presentare una vulnerabilità di tipo XSS.

Output di un messaggio d'errore (Google)
Output di un messaggio d'errore (Google)

Notare che tale vulnerabilità potrebbe essere presente anche se la stringa “stringamalevola” fosse inserita dall’applicazione in qualche altro punto della sua risposta, cioè anche se non fosse mandata a schermo ma magari inserita in un virgolettato all’interno di un header. La presenza, all’interno della risposta dell’applicazione, della stringa da noi creata, è, tuttavia, condizione necessaria ma non sufficiente perchè la suddetta applicazione risulti vulnerabile a cross-site-scripting.

Allo stesso tempo, infatti, deve anche verificarsi, da parte dell’applicazione, una** fallace sanitizzazione della stringa inserita** in input dall’utente. Supponiamo di richiedere l’URL

http://google.com/<span style="color: #0d1f63;"><script>alert(123)</script></span>

Immaginiamo allora che l’applicazione risponda con il seguente messaggio: “Error Message, the requested url http://www.google.com/%3Cscript%3Ealert(123)%3C%2Fscript%3E_ was not found_”. In questo caso, l’applicazione ha sanitizzato correttamente i caratteri “<”, “>” e “/”, impedendo che lo script da noi inserito fosse eseguito.

Sanitizzazione dell'input avvenuta con successo (Google)
Sanitizzazione dell'input avvenuta con successo (Google)

Di fronte ad un tentativo, da parte dell’applicazione web, di sanitizzare le nostre stringhe malevole, esistono differenti stratagemmi che possiamo mettere in atto per** aggirare tale protezione** e fare in modo che l’applicazione esegua comunque i nostri script. Nei prossimi paragrafi vedremo i principali metodi per aggirare la sanitizzazione di codice Javascript.

Principali linee guida

Richiesta XSS client server
Richiesta XSS client server

Potenzialmente, esistono infiniti modi di creare nella nostra applicazione vittima un comportamento inatteso e, dunque, una sanitizzazione fallace del nostro codice. Quantunque sia impossibile elencarli tutti, è tuttavia possibile ridurre queste infinite possibilità a pochi e semplici schemi di pensiero ricorrenti, che possono facilmente essere ricordati e, di conseguenza, applicati. Vediamoli insieme:

Evadere la sanitizzazione di script , <, >:

Una delle possibilità più frequenti è che l’applicazione si protegga dai caratteri script, “<”, “>”. In questo caso, esistono principalmente due modi di ingannare tale schema di difesa:

  • Il primo metodo è codificare tali caratteri in un qualche modo che non venga sanitizzato dall’applicazione. Per esempio, se l’applicazione sanitizza “<”, non è detto che essa sanitizzi anche “3C” o “PA==”. Inviando in input la nostra stringa codificata, esiste, dunque, la possibilità che l’applicazione non applichi alcuna sanitizzazione, e che la stringa venga poi decodificata dall’applicazione stessa, dando vita all’esecuzione del nostro script. Se base64 viene sanitizzato, non è detto che lo stesso avvenga, ad esempio, per UTF-8. Provate dunque tutti i formati di codifica a vostra disposizione. A tal fine, esistono siti web gratuiti e veramente completi che eseguono codifica e decodifica di stringhe arbitrarie.
  • Un altro modo per evitare la sanitizzazione di script, è rompere il pattern di sanitizzazione. Infatti, se l’applicazione sanitizza la stringa script per intero, vi è la possibilità che inviando la stringa <<script>> o la stringa <<scr<<script>>ipt>>, la sanitizzazione fallisca e il vostro codice venga eseguito con successo. Notate che non vi è un unico modo di eseguire questo attacco. A seconda della risposta dell’applicazione alle vostre stringhe, dovrete regolarvi adattando il vostro input, quindi anche le stringhe <scr<SCRIPT>ipt> o <scr%00ipt> potrebbero funzionare.Il trucco è capire, osservando la risposta del server, quale schema di sanitizzazione viene utilizzato e cercare di romperlo innestando una stringa dentro l’altra, raddoppiando i tag, utilizzando null-bytes (%00), maiuscole o codificando il vostro codice.

Evadere la sanitizzazione del virgolettato (doppio e singolo)

Talvolta, è possibile che l’applicazione non sanitizzi affatto il vostro codice e lo lasci così com’è, ma si protegga in altro modo. Facciamo conto di inviare in input il codice

<script>alert(123)</script>. 

Osserviamo, quindi, la risposta del server:

<p> var err = “<script>alert(123)</script>”, var x = 2 </p>

Notate che, pur non avendo modificato il vostro codice, l’applicazione previene l’esecuzione dello stesso, inserendolo nel virgolettato. Quello che dobbiamo chiederci è, quindi, come evadere da questo virgolettato. Il modo più semplice è quello di chiudere il virgolettato prima che il vostro codice venga immesso nell’applicazione, inserendo il seguente codice:

“<script>alert(123)</script>

Il risultato sarà che le prime virgolette, inserite dall’applicazione, vengono chiuse da quelle inserite da voi all’inizio del vostro codice. Segue poi il codice che, come detto sopra, non viene sanitizzato, e poi le virgolette finali che non hanno più alcun significato e che vengono quindi ignorate dall’applicazione stessa. In questo modo, il vostro codice verrà eseguito con successo:

<p> var err = “”<script>alert(123)</script>”, var x = 2 </p>

Tuttavia, non sempre le cose risultano così semplici. Se l’applicazione si protegge da questo tipo di attacco sanitizzando il virgolettato (talvolta sia quello singolo che quello doppio), infatti, la tattica spiegata prima risulterà inefficace. Un modo di rispondere ad una tale tattica di difesa, può essere, nè più nè meno, quello spiegato all’interno del 1° caso.

Utilizzare event-handlers:

nel caso che la vostra stringa venga incorporata direttamente all’interno di due caratteri di tag, è possibile ottenere che il nostro codice venga eseguito anche senza utilizzare “”. Ciò risulta fattibile grazie all’utilizzo degli event-handlers come, per esempio, onload, onclick, onmouseover. Il nostro payload sarà quindi simile al seguente:

http://www.google.com/”onload=”alert(123)”

che risulterà nella seguente risposta da parte dell’applicazione:

<h2 var err=”” onload=”alert(123)” var x = 2> Benvenuti</h2>

Inviare il codice all’interno di una variabile inesistente

Nell’URL: poniamo il caso che il nostro URL si presenti come:

http://www.google.com/search=home

inserendo il nostro codice Javascript come valore di una variabile inesistente, potremmo ottenere che esso non venga sanitizzato:

http://www.google.com/search=home&pippo=<script>alert(123)</script>

Ciò potrebbe funzionare anche con una variabile già esistente dell’URL. In particolare, è importante sottolineare che ogni singolo entry-point dell’applicazione web va testato singolarmente per code-injection attraverso il nostro intercepting proxy (Burp, ZAP o altri). Infatti, criteri di sanitizzazione diversi potrebbero essere applicati a entry-point diversi o, addirittura, alcuni entry-point potrebbero essere sprovvisti di difese. 5. inviando la nostra richiesta dopo il carattere “#”, l’applicazione potrebbe fallire nell’applicare i suoi criteri di sanitizzazione. Un esempio, è il seguente URL:

http://www.google.com/#<script>alert(123)</script>

Conclusioni

Non sempre sarà possibile bypassare i criteri di sanitizzazione di un’applicazione web ma, applicando le linee guida brevemente spiegate in questo articolo, potrete massimizzare le probabilità di riuscire ad eseguire il vostro codice sull’applicazione vittima. Ricordate che un’ultima forma di difesa può essere applicata dal browser, di conseguenza, quando testate un’applicazione, assicuratevi di disabilitare la protezione XSS nel browser e usate browser diversi, poichè, ognuno di essi, implementa difese differenti. Per chi volesse testare le proprie capacità consiglio XSS Game e alert(1) to win.