Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

XSS: teoria e pratica

Cross-site scripting (XSS) vediamo come individuarle e come sfruttarle.
Cross-site scripting (XSS) vediamo come individuarle e come sfruttarle.
Link copiato negli appunti

Introduzione al Cross-Site Scripting

Il Cross-Site Scripting (abbreviato in "XSS") è un tipo di attacco molto comune in cui script malevoli vengono iniettati all'interno di pagine vulnerabili allo scopo di, generalmente, approfittare della loro presunta affidabilità per arrecare danno agli utenti delle stesse.

L'esempio classico è quello di un'attaccante che, aprofittando di una vulnerabilità di questo tipo in una pagina web, inietta del codice javascript capace di rubare dati sensibili (cookie, token di sessione, etc) dagli utenti della pagina stessa.

[ghvideo id=213210 title="The perfect RESTful solution" layout="mp4_inside"]

Cosa significa "iniettare" codice

Ogni applicazione web si appoggia su un'architettura client-server.
Che essa sia un clone di Photoshop o quattro pagine statiche ci sarà sempre un server web che si occuperà di gestire le richieste provenienti dai client (i.e. i browsers) e le rispettive risposte. C'è sempre quindi uno scambio di informazioni.

A livello di protocollo HTTP le richieste dei client contengono informazioni quale l'url della pagina che vogliamo visualizzare, l'user-agent del nostro browser, eventuali cookie e molto altro. A livello applicativo possiamo anche scambiare dati direttamente con le applicazioni stesse attraverso i parametri GET e POST e perfino con i frammenti delle URL (i.e. http://target.com/pagina.html#dato).

Tutti questi dati che il client invia al server/applicazione vengono elaborati e eventualmente utilizzati per costruire le risposte.

Iniettare codice significa forzare questo scambio di informazioni inviando al posto di dati legittimi del codice con lo scopo di includerlo nelle risposte e farlo infine eseguire. Il dato alterato con del codice per questi scopi viene definito in gergo payload.

Prendiamo come esempio una semplicissima applicazione web:

<html>
<head>
</head>
<body>
<?php 
    if (isset($_REQUEST["nome"])) {
?>
    <h1>Ciao <?php echo $_REQUEST["nome"] ?>!</h1>
<?php
    }
    else {
?>
    <h1> Ciao sconosciuto!</h1>
<?php } ?>
</body>
</html>

Lo script controlla che la richiesta contenga la variabile nome (GET o POST) e, se presente, ne stampa il contenuto.

L'utilizzo teorico di questo script è questo:

http://sitotarget.com/pagina.php?nome=Liutprando

Proviamo a fare di meglio. Che succede se invece di un nome inserisco del javascript?

http://sitotarget.com/pagina.php?nome=<script>window.alert("OPS!")</script>

Succede questo (sorgente della pagina di risposta):

<html>
<head>
</head>
<body>
<h1>Ciao <script>window.alert("OPS!")</script>!</h1>
</body>
</html>

Il codice che ho iniettato viene regolarmente interpretato dal browser e produce l'apertura di un alert. Ovviamente questo non è il comportamento desiderato, quella variabile dovrebbe contenere un nome proprio eppure, senza nessun controllo sull'input dell'utente, è stato possibile inserire del JavaScript. Questa è una vulnerabilità di tipo cross-site scripting.

Nota: la maggioranza dei browser moderni dispone di protezioni contro le XSS più semplici come quelle illustrate negli esempi. Il principio di funzionamento però non cambia.

È solo una innocua alert!

È vero: una alert non è niente di pericoloso. Ma se guardiamo oltre le apparenze si osserva che quello che realmente accade in un caso di cross-site scripting è che un attaccante può far eseguire il suo codice al browser di una vittima.

Questo è importante perché non si tratta più di un attacco da remoto dove l'attaccante attivamente si adopera per violare un bersaglio. In questo caso l'attaccante è già dentro.

Vediamo alcune semplice conseguenze. Ad esempio prendiamoci un cookie:

http://target.com/pagina.php?nome=<script>window.alert(document.cookie)</script>

Il cookie è come un badge di autenticazione. Quando facciamo il login in una applicazione ci viene di solito consegnato un cookie così che ogni volta che dobbiamo rientrare non siamo costretti ad inserire di nuovo le credenziali. Beh, vi ho appena copiato il badge. (La sto facendo semplice, in realtà esistono dei meccanismi di protezione a livello di cookie ma può ancora capitare qualcosa del genere)

Perché fermarci qui quando possiamo fare... phishing:

http://target.com/pagine.php?nome=<iframe   src="http://www.google.it">

In questo caso non viene iniettato JavaScript ma un semplice iframe che oscura la pagina reale e ci mostra un'altra pagina (in questo caso Google). Ma niente vieta di mostrare un clone della pagina di login di Gmail che si occupa di registrare le vostre credenziali. E così via.

E tutto questo è possibile per un semplice motivo: nessuno si è preoccupato di filtrare l'input dell'utente.

Filtri e codifiche

C'è una regoletta d'oro che dice: mai fidarsi del client. Questo significa che ogni informazione inviata dal client andrebbe accuratamente controllata per prevenire problemi come, appunto, il cross site scripting.

Per mitigare la minaccia è consuetidine e buona pratica filtrare gli input dell'utente per eliminare combinazioni di caratteri e disinnescare una potenziale infiltrazione.

Prendiamo come esempio una ipotetica query string generata da un input di ricerca su una pagina web:

http://target.com/search.php?q=Articoli%20Sicurezza

Il parametro q contiene il contenuto della ricerca effettuata dall'utente.
Si suppone che tale parametro difficlmente conterrà caratteri non alfanumerici e quindi si può filtrare il valore in modo tale da depurarlo di caratteri speciali che potrebbero essere utili per costruire un payload, as esempio:

<, >, ", '. L'applicazione di un filtro è detta input sanitization.

In questo modo è possibile disinnescare una buona quantità di minacce anche se purtroppo esisterà sempre per un attaccante un piccolo margine di manovra per effettuare la filter evasion (evasione dai filtri), cioè l'iniezione di payload capaci di eludere un filtro. Questa possibilità è una diretta conseguenza della grande varietà di tecnologie di cui è composto il web.

Le pagine web possono infatti essere costruite con codifiche diverse e browser diversi possono avere interpretazioni differenti delle stesse. Questa grande varietà di scenari rende possibile la costruzione di payload codificati.

Senza entrare in altri dettagli il lettore può approfondire consultando la storica XSS Cheatsheet che seppure datata rimane un'ottima fonte di ispirazione.

Stesso attacco, tipi diversi

Le XSS vengono suddivise in tre tipi a seconda del tipo di impatto e del punto di iniezione di un payload:

  • XSS Riflesse (reflected)
  • XSS Persistenti (stored)
  • XSS di tipo DOM (dom-based)

Nel primo tipo, il più comune, il payload viene eseguito nel momento dell'iniezione.

Nelle XSS persistenti invece il payload viene incorporato in modo permanente nella pagina web e viene eseguito ogni volta che viene caricata. Ad esempio in applicazioni in cui l'input dell'utente viene salvato in un database e riutilizzato successivamente, come un forum o un guestbook.

Nelle XSS di tipo DOM il payload viene iniettatto direttamente nel javascrit di una pagina ed è eseguito quindi al livello del document object model. Il DOM permette a script dinamici, come appunto il javascript, di interfacciarsi agli elementi di una pagina web come i campi form, l'url, i cookie, etc. In questo modo se nella pagina vulnerabile è presente uno script che si interfaccia ad uno di questi elementi e se il valore di questi ultimi è controllabile da un attaccante allora è possibile l'iniezione e l'esecuzione di un payload.

Ad esempio se una pagina presenta il seguente script:

...
<script>
    document.write("L'indirizzo di questa pagina è + " + document.loaction.href + ".");
</script>
...

È possibile per un attaccante iniettare un payload attraverso frammento della URL della pagina:

http://target.com/pagina.html#<script>window.alert('DOM XSS')</script>

Per approfondimenti vi consiglio di consultare l'eccellente DOMXSS Wiki.

Conclusioni

Le vulnerabilità di tipo cross-site scripting sono, come abbiamo visto, molto semplici da exploitare e, purtroppo, sono anche estramamente comuni: secondo la OWASP Top 10 sono infatti la 2° minaccia sul web per diffusione.

Se siete degli sviluppatori il consiglio è quello di prevenirle implementando un buon filtraggio degli input degli utenti (la wiki del progetto OWASP è ricca di consigli al riguardo).

Come raccomandazione generale invece è sempre meglio aumentare il livello di paranoia: ponete sempre attenzione ai link che state per cliccare (specialmente quelli dei servizi di shortening come bitly che vengono utilizzati per *mascherare*), abilitate le protezioni del vostro browser e utilizzate strumenti specifici di protezione come il validissimo NoScript.


Ti consigliamo anche