Le vulnerabilità di tipo cross-site scripting sono molto comuni e facili da sfruttare perché un browser non vede la differenza tra il codice scritto dallo sviluppatore del sito e un comando malevolo inserito da un estraneo.
Spesso pensiamo che solo chi fa errori come condividere la propria password possa subire il furto dell’account, ma in realtà su un sito sotto attacco XSS basta visitare per sbaglio una pagina infetta perché un hacker possa rubare la tua sessione, prendere il controllo del tuo profilo e agire a nome tuo, e senza che tu te ne accorga.
Per aiutarti a prevenire situazioni del genere, in questa guida vedremo cos’è e come funziona il cross-site scripting, le conseguenze per chi lo subisce e come difendersi, insieme ai principali errori da evitare.
Indice
Cos’è il cross-site scripting (XSS)
A seconda dei punti di vista, il cross-site scripting (XSS) è una vulnerabilità dei siti web o il tipo di attacco informatico che la sfrutta. Attraverso l’XSS gli hacker possono inserire nelle pagine visitate dagli utenti codice JavaScript che esegue azioni fraudolente come rubare dati, modificare la pagina o compiere operazioni a insaputa del visitatore.
La vulnerabilità XSS è tipica dei siti che accettano input, cioè dati che arrivano da utenti – per esempio attraverso moduli di contatto, barre di ricerca o commenti –, ma anche da fonti esterne, come nel caso di URL, cookie, header HTTP, database o API. Ovviamente solo se non applicano gli accorgimenti necessari per la sicurezza del sito.
Come funziona un attacco XSS
Quando un sito accetta dati esterni senza controllarli, per esempio attraverso moduli o barre di ricerca, gli hacker possono inserire nell’HTML codice JavaScript, che il browser eseguirà come se facesse parte della pagina.
Quello che fanno in pratica è digitare al posto di un normale testo una stringa, racchiusa nei tag:
<script></script>
Il sito la riceve e la include nel codice HTML che invia al browser. Lo script entra così a far parte del DOM, il modello attraverso il quale il browser rappresenta la struttura della pagina, e a quel punto non viene più distinto dal codice legittimo.
A seconda del tipo di attacco cross-site scripting, gli hacker possono distribuire il link alla pagina infetta tramite email, sms o chat, oppure aspettare che gli utenti ci arrivino da soli navigando sul sito.
A differenza degli attacchi DDoS – in cui un gran numero di dispositivi invia richieste simultanee a un server per sovraccaricarlo – gli attacchi XSS non puntano a rendere un sito irraggiungibile ma a usarlo in modo illecito.
Tipi di attacchi XSS
Esistono 3 diversi tipi di attacco cross-site scripting:
- XSS riflesso
- XSS persistente
- XSS basato su DOM.
Ciò che li distingue è principalmente il modo in cui il codice malevolo viene consegnato alla vittima e se viene memorizzato o meno sul server.
XSS riflesso
L’XSS riflesso (reflected XSS) è la forma più comune di attacco cross-site scripting. In questo caso gli hacker inseriscono il codice malevolo come parametro alla fine dell’URL di una pagina esistente, che assumerà una forma simile a:
https://sito.it/search?q=<script>codice_malevolo</script>
Quando un utente clicca sul link malevolo, il browser include l’URL nell’HTML della pagina. Il server “lo riflette”, cioè lo restituisce nella risposta, e il browser lo esegue.
ll codice malevolo non viene salvato dal sito ma esiste solo temporaneamente nella richiesta e nella risposta: ecco perché L’XSS riflesso viene chiamato anche XSS non persistente.
L’attacco può partire solo al clic dell’utente, quindi gli hacker distribuiscono il link tramite email, messaggi o post sui social – nascosto dietro pulsanti o testi – ancora apparentemente innocui – e usano tecniche di ingegneria sociale per indurre le persone ad aprirlo. Per esempio messaggi o email che ti avvisano che il tuo account verrà sospeso se non verifichi subito i tuoi dati, che ti sarà capitato tante volte di ricevere, spesso contengono pulsanti che puntano a URL manipolati di questo tipo.
XSS persistente
L’XSS persistente (stored XSS) è un tipo di attacco cross-site scripting in cui il codice malevolo viene salvato sul server – per esempio in un database – dopo essere stato inserito attraverso sezioni come commenti, forum o impostazioni del profilo utente.
L’hacker inserisce il codice attraverso un campo di input del sito, cioè uno di quelli che servono ad acquisire dati dagli utenti e, se non sono state previste misure di sicurezza per evitarlo, il codice viene memorizzato così com’è e poi mostrato agli utenti quando arrivano sulla pagina. All’apertura del contenuto, il loro browser riceve il codice insieme al resto dell’HTML e lo esegue.
Come suggerisce il nome, l’XSS persistente è insidioso perché il codice malevolo può continuare a colpire tutti i visitatori della pagina finché non viene rimosso dall’HTML. Per verificare la presenza di infezioni di questo tipo puoi eseguire scansioni del sito, che permettono di individuare e correggere le anomalie.
XSS basato su DOM
Nell’XSS basato su DOM la vulnerabilità si trova nel codice JavaScript della pagina – l’insieme delle istruzioni che il browser scarica ed esegue localmente per rendere la pagina web interattiva e dinamica –, quindi tutto avviene nel browser durante l’esecuzione della pagina.
Il server restituisce una risposta normale, ma lato client il JavaScript del sito legge dati da una fonte non controllata, come un parametro nell’URL o il frammento dopo il simbolo #, e li scrive direttamente nel DOM senza verificarne il contenuto. A quel punto il browser interpreta quel contenuto come codice e lo esegue.
L’XSS basato su DOM è il tipo di attacco cross-site scripting più difficile da individuare proprio perché il server non è coinvolto e non registra nulla di anomalo: tutto accade nel browser, in modo invisibile sia al proprietario del sito che all’utente.
Ecco una tabella che può aiutarti a distinguere i tre tipi di attacco XSS:
Tipo di attacco | Caratteristica principale | Dove avviene | Quando si attiva |
|---|---|---|---|
XSS riflesso | Il codice non viene salvato | Server poi browser | All’apertura del link |
XSS persistente | Il codice viene salvato | Server (database) poi browser | A ogni visualizzazione della pagina |
XSS basato su DOM | Tutto avviene nel browser | Browser | Durante l’esecuzione di JavaScript |
Esempi di XSS
Gli attacchi cross-site scripting possono colpire attraverso funzionalità presenti sulla maggior parte dei siti come una sezione commenti, una barra di ricerca, un’applicazione che aggiorna la pagina in tempo reale.
L’esempio più classico riguarda i moduli per i commenti, dove gli utenti possono inserire contenuto testuale che viene salvato nel database e ripubblicato come HTML. Se il sito non controlla quello che riceve, chiunque può inserire codice JavaScript invece di testo normale, che verrà poi eseguito dal browser come se fosse parte legittima del sito.
Spesso gli hacker sfruttano anche il fatto che la barra di ricerca di WordPress e di altri CMS genera un URL con parametri, e che molti siti mostrano nella pagina dei risultati anche le parole chiave inserite. Se il sito non filtra quel valore prima di includerlo nella pagina, un hacker può inserire nel campo di ricerca uno script che finirà nell’URL e poi nell’HTML e che verrà eseguito dal browser. Il link col parametro di ricerca potrà essere inoltrato attraverso diversi canali di messaggistica come capita abitualmente nelle truffe informatiche.
Ancora più insidioso è il caso delle applicazioni che utilizzano JavaScript per aggiornare la pagina in tempo reale, come alcune web app, applicazioni SPA o ecommerce. In questi contesti, il codice del sito preleva dati direttamente dall’URL o da altri elementi del browser e li inserisce nel DOM senza una preventiva bonifica. Poiché l’intera operazione avviene localmente sul dispositivo dell’utente, un hacker potrebbe iniettare script malevoli che vengono eseguiti istantaneamente, il tutto senza che il server riceva o registri alcuna attività anomala. Per fortuna la maggior parte delle applicazioni moderne è progettata con adeguate misure di sicurezza che riducono significativamente questo rischio.
Conseguenze di un attacco XSS
Le conseguenze di un attacco XSS dipendono dal contesto, ma possono essere gravi perché il codice agisce con i privilegi dell’utente che lo esegue involontariamente.
Uno scenario comune è il furto dei cookie di sessione, grazie ai quali gli hacker possono impersonare l’utente e accedere al suo profilo e impossessarsi di informazioni riservate, credenziali per l’accesso o dati delle carte di credito.
Quando l’attacco colpisce un amministratore, le conseguenze si estendono a tutto il sito: per esempio attraverso il cross-site scripting è possibile modificare il contenuto della pagina e pubblicare messaggi offensivi o di propaganda, informazioni false e fake news.
L’attacco XSS può essere un mezzo per reindirizzare i visitatori verso siti di phishing, nei quali le informazioni inserite dall’utente vengono acquisite dagli hacker. In questi casi viene iniettato uno script che forza l’apertura di un sito esterno che imita una piattaforma su cui gli utenti sono abituati a eseguire l’accesso.
Differenza tra XSS e CSRF
Cross-site scripting (XSS) e cross-site request forgery (CSRF) sono due attacchi molto diversi che possono essere confusi perché hanno un nome simile e coinvolgono entrambi il browser e le richieste HTTP.
La prima differenza sta nel funzionamento e nell’obiettivo, perché il CSRF fa in modo che l’utente invii una richiesta al server senza rendersene conto, mentre l’XSS punta a eseguire codice nel browser della persona che ha aperto la pagina infetta (e non richiede nessun’altra azione da parte sua per attivarsi).
Nel CSRF il browser non esegue nulla di anomalo ma si limita a inviare una richiesta che il server considera valida perché proviene da un utente autenticato. Nell’XSS invece il browser esegue codice malevolo perché si trova già nella pagina.
In generale le conseguenze dell’XSS tendono a essere più gravi perché, a differenza del CSRF, permette ai criminali informatici di leggere le risposte del server e sottrarre dati.
Oltre alla tipologia di attacco, capita che si confondano i metodi per la protezione da CSRF e XSS. Questo può essere pericoloso perché i token anti-CSRF non proteggono dal cross-site scripting; per di più se sono presenti vulnerabilità XSS anche i sistemi di difesa CSRF possono essere aggirati.
XSS (cross-site scripting) | CSRF (cross-site request forgery) | |
|---|---|---|
Scopo | Eseguire codice nel browser della vittima | Far inviare richieste al server a insaputa dell’utente |
Come funziona | Il codice malevolo viene inserito nella pagina e interpretato dal browser | L’utente autenticato viene indotto a inviare una richiesta valida |
Ruolo dell’utente | Basta che apra la pagina infetta | Deve compiere un’azione (es. clic su link) |
Esecuzione di codice | Sì, nel browser | No |
Accesso ai dati | Può leggere e inviare dati | Non può leggere la risposta del server |
Conseguenze tipiche | Phishing, modifica del sito e altre azioni non autorizzate a nome dell’utente | Operazione non autorizzata (es. cambio password o trasferimenti di denaro) |
Come difendersi dagli attacchi XSS
Per difenderti dagli attacchi XSS devi applicare sempre un principio fondamentale: non considerare mai affidabili i dati che arrivano dall’esterno, a prescindere dalla fonte. Questo implica che dovrai adottare una serie di misure di sicurezza che filtrano gli input, sia lato server che lato client.
Esistono diversi metodi per proteggere il tuo sito da attacchi cross-site scripting. Più riesci a implementarne, più al sicuro sarai.
Validazione e sanitizzazione degli input
La validazione e la sanitizzazione degli input sono due tecniche che possono dare buoni risultati se messe insieme.
La validazione consiste nel verificare che i dati rispettino un formato atteso, per esempio che un campo numerico contenga solo numeri o che un indirizzo email presenti una struttura standard.
La sanitizzazione serve invece a rimuovere o neutralizzare i contenuti potenzialmente pericolosi prima che vengano elaborati.
Escape dell’output
Una delle difese più efficaci contro l’XSS è l’escape dell’output, letteralmente una messa in sicurezza del contenuto che il sito genera e invia al browser. Questa tecnica consiste nel trasformare i caratteri speciali in entità sicure prima di inserirli nella pagina, in modo che il browser possa interpretare gli elementi solo come testo e non come codice eseguibile, HTML o JavaScript.
Si tratta quindi di convertire i caratteri speciali nelle loro rappresentazioni testuali, diverse a seconda del contesto, che può essere HTML, JavaScript, un attributo o un URL. Per esempio nel caso dell’HTML “&” viene convertito in “&” e “>” in “>”.
Rendere sicure le API del DOM
Le API del DOM sono le funzioni e i metodi forniti dal browser per leggere e modificare la struttura della pagina, alcune delle quali inseriscono i contenuti direttamente al suo interno. Questo meccanismo è rischioso se i dati non vengono sanitizzati o sottoposti a escape, perché possono essere interpretati dal browser come codice HTML o JavaScript ed eseguiti immediatamente.
Ecco perché è importante che chi scrive codice JavaScript scelga metodi che trattano il contenuto come testo semplice – per esempio textContent –, anziché metodi che lo interpretano come HTML eseguibile – come innerHTML. È una precauzione facile da adottare ma molto efficace nel ridurre il rischio di XSS basato sul DOM.
Content Security Policy (CSP)
La Content Security Policy consiste in una serie di norme per la sicurezza che definiscono quali risorse può caricare ed eseguire una pagina e vengono comunicate dal server al browser tramite un header HTTP.
Le regole impediscono l’esecuzione di codice che non rispetti determinati requisiti, per esempio possono filtrare gli script che provengono da altri siti o addirittura da tutti i plugin. Da una parte aiutano a prevenire gli attacchi XSS, ma dall’altra possono interferire con le funzionalità del sito, quindi devono essere gestite con attenzione.
Protezioni nei framework
I framework – un insieme di strumenti già pronti che aiutano a sviluppare siti web in modo più veloce e sicuro – oggi includono protezioni contro l’XSS, per esempio l’escape automatico, e liberano i programmatori da una parte del lavoro. Perché siano efficaci è importante non disabilitare le impostazioni predefinite per la sicurezza e mantenerli sempre aggiornati.
Protezione dei cookie di sessione
I cookie – i file che il sito salva nel browser per mantenere attiva la sessione dell’utente – possono essere intercettati in caso di attacco, se non sono protetti correttamente.
I cookie possono essere messi al sicuro grazie a due attributi, cioè istruzioni che il server invia al browser quando li crea.
L’attributo HttpOnly impedisce l’accesso ai cookie tramite JavaScript e così rende più difficile il loro furto in caso di attacco XSS.
L’attributo Secure garantisce invece che i cookie vengano trasmessi solo su connessioni cifrate (HTTPS). Insieme possono ridurre significativamente l’impatto di un attacco.
Attivazione di plugin di sicurezza
Su CMS come WordPress è possibile installare un plugin di sicurezza che riduca le vulnerabilità XSS, per esempio filtrando gli input sospetti. Tieni conto però che questi plugin rallentano WordPress ed è sempre meglio agire prima lato server, scegliendo un hosting WordPress sicuro.
Errori comuni nella prevenzione XSS
Uno degli errori più gravi nel campo delle vulnerabilità XSS è validare solo gli input, cioè i dati in ingresso, e non applicare l’escape dell’output. Infatti un input potrebbe sembrare innocuo e non esserlo, quindi è importante trasformarlo in testo semplice in modo che non possa essere letto come script.
Un altro errore possibile è applicare a tutti i contesti lo stesso tipo di codifica – ovvero la trasformazione di caratteri speciali in sequenze di testo non eseguibile –, senza considerare che HTML, attributi, JavaScript e URL richiedono regole diverse.
Sul fronte del DOM invece, una cattiva pratica diffusa è usare innerHTML invece di metodi sicuri come textContent per inserire contenuti dinamici.
Anche basare la sanitizzazione degli input su filtri che dipendono da blacklist, bloccando stringhe o caratteri specifici come <script> o alert(), è un approccio inefficace perché esistono molte varianti per aggirarlo.
Capita anche che gli sviluppatori si limitino a controlli lato client e trascurino le validazioni lato server, non testino le protezioni oppure si affidino completamente a plugin o librerie di terze parti che possono non coprire tutti i casi o contenere a loro volta vulnerabilità.
Conclusioni
In questa guida abbiamo visto che il cross-site scripting è una vulnerabilità che colpisce i siti che accettano dati dall’utente senza controllarne il contenuto, permettendo agli hacker di inserire nelle pagine codice JavaScript eseguito dal browser come se fosse legittimo.
I tre tipi di attacco XSS – riflesso, persistente basato sul DOM – possono avere conseguenze gravi come la sottrazione di dati sensibili o la perdita del controllo sul proprio sito.
Per difendersi bisogna affiancare più misure scegliendo tra quelle disponibili come validare gli input, effettuare l’escape dell’output, usare metodi sicuri per il DOM, configurare una Content Security Policy e proteggere i cookie con gli attributi HttpOnly e Secure.
E tu stai cercando di eliminare questo tipo di vulnerabilità? Se ti va, parliamone nei commenti.
Pronto a costruire il tuo sito WordPress?
Prova il nostro servizio gratuitamente per 14 giorni. Nessun impegno, nessuna carta di credito richiesta.