Cos’è il Cross-Site-Scripting (XSS)
Il cross-site scripting (XSS) è una vulnerabilità del web che permette agli hacker di introdurre (inject) comandi indesiderati nel codice lato client legittimo (solitamente JavaScript) eseguito da un browser per conto dell’applicazione web.
Si stima che circa il 40% degli attacchi informatici sia di tipo XSS e che oltre il 60% dei siti web sia vulnerabile.
XSS può essere di tipo “reflected” oppure “storage“. Il primo caso si verifica quando un’applicazione riceve dati non sanificati da una richiesta HTTP (es. i termini di una ricerca) e li include in modo non sicuro nella risposta immediata, nel secondo caso viene invece salvato nel database e incluso in risposte future.
Reflected Cross Site Scripting
Supponiamo ad esempio di avere un form di ricerca i cui parametri vengano salvati nell’url:
https://sitononsicuro.com/search?term=keywordRicercata
Il sito potrebbe mostrare il dato nel flusso del documento in modo più o meno semplice ad esempio:
<p>Hai cercato: keywordRicercata</p>
In assenza di sanificazione dei dati un malintenzionato potrebbe includere un payload nel parametro e farlo girare sulla pagina:
https://sitononsicuro.com/search?term=<script>/* Codice dannoso */</script>
Questo risulterebbe in un caricamento involontario dello script nell’interfaccia utente:
<p>Hai cercato: <script>/* Codice dannoso */</script></p>
Ogni volta che un utente visita l’url modificato dall’hacker, magari cliccando su un link malevolo, lo script verrà fatto girare nel browser dell’utente. Potrebbe ad esempio rubare cookie.
Storage Cross-Site Scripting
Si definisce storage (o “persistent”) perchè c’è un salvataggio dei dati in un database come ad esempio i commenti di un blog. Supponiamo, appunto, che un sito permetta agli utenti di inserire commenti ad un blog post. Il commento può essere inviato con una richiesta HTTP di tipo POST:
POST /post/comment HTTP/1.1
Host: sitononsicuro.com
Content-Length: 100
postId=3&comment=Questo+post+è+molto+bello.&name=Pinco+Pallino&email=pinco%40pallino.it
L’invio della richiesta POST mostrerà in interfaccia utente il commento:
<p>Questo post è molto bello.</p>
Un hacker potrebbe inviare un commento codificato con script malevolo:
comment=%3Cscript%3E%2F*%2BCodice%2Bdannoso%2B*%2F%3C%2Fscript%3E
Il sito salva il commento e lo mostra ogni volta un utente visita la pagina:
<p><script>/* Codice dannoso */</script></p>
Questo, può dar modo all’hacker di prendere il controllo della sessione dell’utente.
Come proteggersi
La misura più importante per evitare attacchi XSS è la sanificazione dei dati.
Sanificare i dati significa rimuovere o neutralizzare gli input, ossia i dati forniti dagli utenti tramite form, URL, API, ecc. L’obiettivo è rimuovere o neutralizzare qualsiasi dato che possa essere interpretato come codice eseguibile dal browser. Ad esempio, tag HTML come <script> o attributi eventi come onclick possono essere rimossi o trasformati in entità sicure (come ad esempio sostituendo < con <).
Librerie per sanificazione dei dati
DOMPurify: è una libreria molto popolare per la sanificazione di HTML, SVG e MathML. E’ scritta in JavaScript, si installa tramite il package manager di Node (NPM) e può essere utilizzata ad esempio in Vue, React e Angular per rimuovere parti indesiderate del codice inviato dagli utenti prima che possa causare danni. Offre ampia customizzazione.
Sanitize-HTML: altra libreria popolare in JavaScript che funziona in modo molto simile a DOMPurify e si installa con NPM.
OWASP Java HTML Sanitizer: specifica per applicazione Java, anche questa permette di configurare regole di sanificazione che eliminano o trasformano gli elementi HTML e gli attributi in base alle esigenze.
Bleach: è una libreria per la sanificazione HTML in Python, molto utilizzata per applicazioni web basate su Django. Si basa su html5lib.
PHP, sebbene abbia varie librerie ha anche funzioni di filtraggio native come “filter_var” con vari filtri di sanificazione:
<?php
// Esempio di stringa inserita dall'utente
$inputUtente = "<script>alert('Hacked!');</script>Ciao! Come stai? <b>Bene</b>";
// Utilizzo di filter_var con FILTER_SANITIZE_FULL_SPECIAL_CHARS
$testoSanificato = filter_var($inputUtente, FILTER_SANITIZE_FULL_SPECIAL_CHARS);
echo $testoSanificato;
// Output: Ciao! Come stai? <b>Bene</b>
?>
Nell’esempio sopra, filter_var con il filtro FILTER_SANITIZE_FULL_SPECIAL_CHARS è utilizzato per l’escape di caratteri speciali e i tag HTML.
Oltre alla sanificazione dei dati, per evitare attacchi XSS, si usano gli header CSP (Content Security Policy). E’ un response header ampiamente supportato dai browser più utilizzati. Si utilizza specificando delle “policy” che dicono al browser quali risorse possono essere caricate nella pagina web.
In un web server Apache, ad esempio, si può aggiungere una regola nel file .htaccess o nei file config del virtual host:
<IfModule mod_headers.c>
Header set Content-Security-Policy "default-src 'self'; script-src 'self' https://apis.google.com"
</IfModule>
In questo esempio:
- default-src ‘self’: permette il caricamento di tutte le risorse (come immagini, CSS, font, etc.) solo dallo stesso dominio del documento.
- script-src ‘self’ https://apis.google.com: permette l’esecuzione di script solamente dallo stesso dominio del documento e da https://apis.google.com.
In PHP, puoi impostare l’intestazione CSP direttamente nel tuo script:
<?php
header("Content-Security-Policy: default-src 'self'; script-src 'self' https://apis.google.com");
?>
More from Guide alla sicurezza
Scegliere un nome utente sicuro
Un nome utente sicuro è vitale per la protezione online. Evitare informazioni personali, separare l'username dall'indirizzo email, e garantire unicità …
Crittografia per neofiti: capire le basi
Questo articolo introduce i concetti fondamentali della crittografia, spiegando la differenza tra crittografia simmetrica e asimmetrica e fornendo esempi pratici …