Skip to content

Tutto per WordPress, lo sviluppo web — e non solo

💡 Cross-site scripting (XSS): cos'è e come proteggere il tuo sito nel 2026

💡 Cross-site scripting (XSS): cos'è e come proteggere il tuo sito nel 2026

Nel 2019, quasi il 75% delle grandi aziende ha subito attacchi di cross-site scripting. Sette anni dopo, l'XSS è ancora tra noi. Microsoft ha segnalato 970 casi di XSS chiusi solo da gennaio 2024, e una vulnerabilità del 2025 nel plugin LiteSpeed Cache ha messo a rischio 7 milioni di siti WordPress.

Il problema non è la tecnologia. JavaScript, il linguaggio del web interattivo, alimenta ogni tema, ogni modulo dei commenti, ogni carrello della spesa. Il problema è che un aggressore può costringere il tuo sito a eseguire il proprio codice, e il browser non è in grado di distinguere uno script malevolo da uno legittimo.

Analizziamo i meccanismi dell'XSS, i tre tipi di attacco e i livelli di protezione specifici che mettono al riparo il tuo sito dal cross-site scripting. Con strumenti, esempi di codice e casi reali su WordPress.

💡 Panoramica rapida:

  • Cos'è l'XSS e come un aggressore inietta codice malevolo in un sito affidabile
  • I tre tipi di cross-site scripting (stored, reflected e DOM-based) e le loro differenze
  • Configurazione passo passo di tre livelli di protezione: WAF, escaping dell'output e Content Security Policy
  • Dove cercare le vulnerabilità XSS sul tuo sito e cosa fare se un attacco è già avvenuto

Cos'è il cross-site scripting

Diagramma di un attacco cross-site scripting su un sito web

Il Cross-Site Scripting è un attacco a iniezione in cui un aggressore incorpora uno script malevolo in una pagina di un sito affidabile. Il browser della vittima esegue questo codice perché lo considera parte della pagina legittima. Da qui il nome: lo script arriva «attraversando il confine del sito».

Tecnicamente, il vettore d'attacco non è limitato a JavaScript. Sono possibili vulnerabilità in HTML, Flash, ActiveX e CSS. Ma nella pratica, la stragrande maggioranza degli exploit prende di mira JS. Il motivo: l'accesso all'albero DOM, ai cookie, a localStorage e la capacità di effettuare richieste per conto dell'utente.

In WordPress, le vulnerabilità nascono quasi sempre tramite plugin e temi che gestiscono in modo improprio l'input dell'utente. Moduli dei commenti, barre di ricerca, moduli di contatto, pagine di login: qualsiasi campo che accetta dati e li restituisce in output senza filtrarli diventa un punto d'ingresso. Secondo Claranet, 2570 casi di XSS reflected e stored sono stati rilevati in applicazioni web testate nel 2024.

Come funziona l'XSS

A un aggressore servono due condizioni: un punto d'ingresso per il codice malevolo e l'assenza di filtraggio in output. Nella pratica, ciò si ottiene in due modi: tramite la manipolazione dell'input utente e tramite l'elusione della same-origin policy.

Iniezione tramite input utente

Lo scenario più comune. Un campo utente (barra di ricerca, modulo dei commenti, campo di upload file) accetta non solo testo ma codice eseguibile. Se il plugin o il tema non esegue l'escape dell'output, un <script>alert('XSS')</script> inserito verrà eseguito nel browser di chiunque apra la pagina.

Il problema è più profondo di quanto sembri. Anche sviluppatori esperti non vedono i vettori XSS attraverso campi apparentemente innocui: il caricamento di un file SVG con uno script incorporato, l'inserimento di dati nel campo «username» durante la registrazione, i parametri URL nei redirect. Basta un campo senza esc_url() o esc_attr(), e il sito è esposto.

In un mondo ideale, un campo di ricerca accetta testo semplice e nient'altro. Nell'ecosistema reale di WordPress con oltre 60.000 plugin, questa garanzia è irraggiungibile: è sufficiente un plugin con echo $_GET['q'] senza esc_html().

Elusione della same-origin policy

Illustrazione dell'elusione della same-origin policy del browser

La same-origin policy è una regola di sicurezza fondamentale del browser: gli script di un'origine non possono leggere i dati di un'altra. Una pagina Facebook e una pagina della banca aperte nello stesso browser non si scambiano informazioni. Ma questa regola ha un tallone d'Achille: i cookie di sessione.

Quando fai il login su un sito, il browser crea un cookie di sessione che conferma la tua identità a ogni richiesta. Senza, dovresti inserire la password a ogni navigazione verso una nuova pagina. Il problema è che il browser allega questo cookie a qualsiasi richiesta verso il dominio, incluse le richieste avviate da uno script malevolo.

Schema dell'attacco: un aggressore trova una vulnerabilità XSS su example.com → inietta uno script che legge document.cookie → invia il cookie di sessione al proprio server. Risultato: accesso completo all'account della vittima senza conoscerne la password. I cookie di sessione memorizzano credenziali, contenuto del carrello, informazioni di spedizione: l'intero contesto utente.

I tre tipi di attacchi XSS

Screenshot del gioco educativo Google XSS Game per trovare vulnerabilità

La classificazione XSS si basa su dove e come il codice malevolo raggiunge la vittima. Esistono tre tipi e proteggere il tuo sito richiede la comprensione dei meccanismi di ciascuno.

Stored XSS (tipo I)

Il tipo più pericoloso. Lo script malevolo viene salvato sul server (nel database, nei log, in un campo commento) e viene eseguito ogni volta che la pagina infetta viene aperta. Su WordPress, questo è uno scenario classico: un utente malevolo lascia un commento con un tag <script>, il plugin per i commenti non filtra l'HTML e lo script si attiva per ogni visitatore dell'articolo.

La particolarità dello stored XSS è che l'attacco non deve essere attivato tramite un link di phishing. La vittima visita semplicemente la pagina. Nel 2025, la vulnerabilità CVE-2025-12709 nel plugin Interactions per WordPress era un classico stored XSS dovuto a una sanitizzazione insufficiente dell'input nei selettori di eventi.

Reflected XSS (tipo II)

L'utente malevolo invia alla vittima un link contenente codice malevolo nei parametri URL. Il server "riflette" questo codice nella risposta, ad esempio in un messaggio di errore di ricerca o in una riga "Hai cercato: X". Il browser esegue lo script perché è arrivato nel corpo della risposta da un server considerato affidabile.

Il reflected XSS richiede un'azione attiva da parte della vittima: cliccare un link. Pertanto, l'attacco è spesso mascherato da URL legittimo in un'email di phishing. Su WordPress, un vettore tipico sono i plugin di ricerca che mostrano la query di ricerca senza usare esc_html().

DOM-based XSS (tipo 0)

A differenza dei primi due, qui la vulnerabilità non è nel codice lato server ma nel JavaScript lato client. I dati malevoli non raggiungono mai il server; vengono elaborati direttamente nel browser attraverso metodi non sicuri delle API DOM come innerHTML, document.write() o eval().

L'origine dei dati è l'URL (tramite window.location), document.referrer o qualsiasi altra fonte controllabile sul client. I log del server sono puliti; l'attacco è visibile solo nel browser. Questo XSS è il più difficile da rilevare perché WAF e scanner lato server non lo vedono.

Perché l'XSS è particolarmente pericoloso per WordPress

WordPress è l'obiettivo numero uno per l'XSS per una ragione: l'ecosistema. Degli oltre 60.000 plugin nel repository, non tutti sono sottoposti a una revisione rigorosa per l'escape dell'output. Un plugin con una vulnerabilità compromette l'intero sito.

A settembre 2025, Microsoft ha pubblicato un'analisi sul perché l'XSS rimanga una minaccia 25 anni dopo la sua comparsa. Il punto chiave: la complessità dello stack web moderno rende l'eliminazione completa dell'XSS quasi impossibile, troppi livelli in cui l'escape può essere dimenticato.

Cosa ottiene un utente malevolo tramite XSS su WordPress:

  • Accesso al pannello di amministrazione rubando i cookie di sessione dell'amministratore
  • Iniezione di link nascosti (SEO spam)
  • Download di malware sui computer dei visitatori
  • Sostituzione dei dettagli di pagamento in WooCommerce
  • Defacement di massa delle pagine del sito

Combinato con l'ingegneria sociale, l'XSS diventa un vettore per attacchi sofisticati: dall'installazione di keylogger alla cross-site request forgery.

Come proteggere il tuo sito dagli XSS: tre livelli

Tre livelli di protezione WordPress contro il cross-site scripting

La protezione XSS non si risolve con una singola impostazione. Solo la difesa a più livelli funziona: i plugin di sicurezza bloccano gli attacchi più grossolani, l'escape dell'output chiude i vettori tecnici e la Content Security Policy blocca l'esecuzione degli script a livello di browser.

Livello 1: plugin di sicurezza e firewall

La prima linea di difesa è un plugin WordPress con un Web Application Firewall. Il WAF filtra le richieste in ingresso prima che raggiungano il codice dei plugin e blocca le firme note di attacchi XSS.

Quando scegli un plugin di sicurezza, usa questa checklist:

  • Scansione regolare per malware e CVE note nei plugin installati
  • Firewall con regole per bloccare i pattern XSS nelle richieste
  • Hardening di WordPress: disabilitare XML-RPC, cambiare il prefisso delle tabelle, impedire la modifica dei file dall'admin
  • Gestione centralizzata degli aggiornamenti per tutti i plugin e temi
  • Backup, per poter ripristinare il sito se un attacco dovesse passare

Puoi trovare una selezione di plugin di sicurezza per WordPress con analisi dettagliate delle funzionalità di ciascuno strumento nelle recensioni specializzate sul nostro sito.

Livello 2: validazione ed escape dell'output

Questa è la principale linea di difesa tecnica. La regola è semplice e non negoziabile: nessun dato utente viene inviato al browser senza escape. WordPress fornisce funzioni integrate per questo, e ciascuna è legata a uno specifico contesto di output.

Toolkit di base per sviluppatori WordPress:

1// For output inside HTML tags — between <p> and </p>
2echo esc_html($user_input);
3
4// For HTML attributes — inside value="..."
5echo esc_attr($user_input);
6
7// For URLs in href, src, and other attributes
8echo esc_url($user_url);
9
10// For output inside <textarea>
11echo esc_textarea($user_text);
12
13// For JavaScript variables
14echo esc_js($user_data);
15
16// For allowed HTML tags with dangerous attributes removed
17echo wp_kses_post($user_html);

Il punto chiave: la scelta della funzione dipende dal contesto. esc_html() in un attributo href non ti salverà; l'attaccante inserirà javascript:alert('XSS'). Al contrario, esc_url() dentro un paragrafo lascerà passare un tag <script>. Il contesto determina la funzione.

wp_kses() merita una menzione speciale: un filtro potente che consente solo i tag HTML e gli attributi permessi. Per i contenuti utente (commenti, descrizioni del profilo, campi personalizzati), questo è il livello minimo di filtraggio richiesto.

Livello 3: Content Security Policy (CSP)

La CSP è un header HTTP che dice al browser: «Esegui script solo da queste origini». Questa è l'ultima linea di difesa. Anche se un attaccante avesse iniettato un <script> nella pagina, il browser non lo eseguirà perché gli script inline non sono nella whitelist.

Politica CSP di base per WordPress:

1// In functions.php or via a plugin
2function add_csp_header() {
3 header("Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:;");
4}
5add_action('send_headers', 'add_csp_header');

Una politica restrittiva ('strict-dynamic' invece di 'unsafe-inline') è più sicura ma richiede la configurazione di nonce o hash per ogni script legittimo. Questo è un lavoro sostanziale su un sito con una dozzina di plugin attivi. Inizia con la modalità report-only per raccogliere i log delle violazioni senza rompere il frontend:

1Content-Security-Policy-Report-Only: default-src 'self'; report-uri /csp-report-endpoint

La CSP non sostituisce l'escape. Mitiga le conseguenze degli errori quando l'escape è stato dimenticato da qualche parte.

Video: XSS dalle basi allo sfruttamento

Per vedere l'XSS in azione e capire come trovare vulnerabilità su siti reali, guarda questa analisi di 30 minuti:

Dopo averlo visto, torna ai livelli di protezione qui sopra. Ora avranno senso a livello meccanico, non solo a livello di nomi di funzioni.

⁉️🤔 Domande frequenti

Aggiornare WordPress e i plugin aiuta a proteggersi dagli XSS?

Sì, e questo è il passo di protezione più sottovalutato. Ogni nuova versione di un plugin spesso chiude CVE specifiche, incluse vulnerabilità XSS. La vulnerabilità di LiteSpeed Cache CVE-2025-12450 è stata corretta entro una settimana dalla scoperta, ma 7 milioni di siti che non hanno aggiornato sono rimasti esposti. Abilita gli aggiornamenti automatici per tutti i plugin; i problemi di compatibilità sono rari, mentre una patch mancata colpisce garantito.

Un solo plugin di sicurezza è sufficiente per proteggersi dagli XSS?

No. Un plugin di sicurezza con WAF chiude le firme di attacco note ma non vede le vulnerabilità zero-day e i vettori non standard. Dovrebbe essere il primo livello, seguito dall'escape dell'output nel codice del tema e dagli header CSP. Tre livelli insieme forniscono una protezione che nessuno di essi può fornire da solo.

Come posso verificare se il mio sito ha vulnerabilità XSS?

Inizia con uno scanner gratuito: WPScan, Sucuri SiteCheck, Qualys SSL Labs. Per test più approfonditi, esegui OWASP ZAP (Zed Attack Proxy), uno strumento open-source che fa automaticamente fuzzing dei campi di input e cattura gli XSS riflessi. Importante: gli scanner automatici non vedono gli XSS basati su DOM; questo richiede un audit manuale del codice JavaScript del sito.

È possibile eliminare completamente gli XSS su un sito di grandi dimensioni?

L'eliminazione completa degli XSS su un sito con dozzine di plugin e un tema personalizzato è un obiettivo vicino all'ideale ma difficile da raggiungere pienamente. Ogni nuovo plugin, ogni aggiornamento del tema, ogni snippet personalizzato in functions.php è un potenziale punto di ingresso. Un obiettivo realistico: tre livelli di protezione, aggiornamenti automatici, audit trimestrali e CSP in modalità report-only. In questo modo catturerai la stragrande maggioranza degli attacchi in una fase iniziale.

Cosa devo fare se il mio sito è già stato attaccato tramite XSS?

Cambia immediatamente tutte le password e reimposta le chiavi di sessione in wp-config.php usando il generatore di WordPress. Poi ripristina il sito da un backup pulito. Dopo il ripristino, installa un plugin di sicurezza, aggiorna tutti i plugin e i temi alle ultime versioni e aggiungi un header CSP in functions.php. Le password devono essere cambiate perché l'XSS spesso ruba i cookie di sessione dell'amministratore.

XSS e SQL injection sono la stessa cosa?

No, anche se entrambi sono attacchi a iniezione. L'SQL injection prende di mira il database attraverso una query SQL; l'attaccante può leggere, modificare o eliminare tabelle. L'XSS prende di mira il browser dell'utente attraverso JavaScript; l'obiettivo è rubare sessioni, mostrare form di phishing o alterare il contenuto della pagina. Hanno vettori diversi, funzioni di protezione diverse ($wpdb->prepare() per SQL, esc_html() per XSS) e conseguenze diverse. Ma in pratica, spesso arrivano insieme: l'XSS viene usato per veicolare l'SQL injection attraverso il pannello di amministrazione.

Bisogna temere l'XSS nel 2026

L'XSS non è scomparso, ma difendersi è diventato routine ingegneristica, non magia. Tre livelli (un plugin con WAF, escape dell'output in tutti i punti di contatto con l'utente e un header CSP) chiudono la stragrande maggioranza dei vettori. Più gli aggiornamenti automatici per plugin e temi, così le patch arrivano prima degli exploit.

Se al momento non stai usando nessuno di questi livelli, inizia installando un plugin di sicurezza e abilitando gli aggiornamenti automatici nell'admin di WordPress. Questo richiede 10 minuti e chiude i punti di ingresso più grossolani. Poi torna su questo articolo quando sei pronto per implementare l'escape e la CSP.