51 05/04/2026 07/04/2026 9 min

Difendere un WAF dai payload XSS più insidiosi non significa inseguire ogni singola stringa malevola. Significa costruire un sistema che riconosca contesto, normalizzazione, variazioni sintattiche e tentativi di bypass prima che il traffico raggiunga l’applicazione. Un WAF efficace non vive di sole blacklist: lavora su decoding, canonicalizzazione, firme robuste, regole comportamentali e validazione del contesto applicativo.

Il problema dell’XSS è che raramente si presenta in forma pulita. I payload moderni usano encoding multipli, separatori ambigui, eventi HTML poco noti, vettori su attributi, SVG, template injection, JSON contaminato e frammenti che diventano pericolosi solo dopo una trasformazione lato server o lato browser. Per questo la difesa migliore è stratificata: il WAF deve bloccare ciò che è evidentemente malevolo, ridurre le ambiguità e inviare all’applicazione solo traffico più prevedibile.

Il principio corretto: non cercare solo "script"

Il classico errore è filtrare solo la parola script. È un controllo debole, facilmente aggirabile con encoding, concatenazioni, tag alternativi, eventi HTML e contesti non testuali. Un payload XSS può non contenere mai la stringa <script> e risultare comunque eseguibile.

Un WAF moderno deve quindi osservare almeno quattro livelli:

  • la forma grezza della richiesta;
  • la richiesta dopo decoding e normalizzazione;
  • il contesto in cui il dato verrà riflesso o memorizzato;
  • il comportamento osservabile del client e della pagina.

Se uno di questi livelli manca, il bypass diventa molto più probabile. La difesa solida non è una firma singola, ma una combinazione di controlli coerenti.

Le famiglie di payload da considerare

I payload XSS più insidiosi tendono a sfruttare una di queste famiglie:

  1. Encoding multiplo: URL encoding, double encoding, HTML entities, Unicode, UTF-7 residuo in sistemi legacy, caratteri misti e varianti case-insensitive.
  2. Injection in attributi: chiusura di virgolette, uso di handler come onerror, onload, onfocus, oppure attributi SVG e MathML.
  3. Contesti scriptless: SVG, URL javascript:, CSS injection, data URI, meta refresh, template delimiters e frammenti che diventano pericolosi dopo il rendering.
  4. Polyglot payload: input che sembra innocuo in un contesto ma diventa eseguibile in un altro.
  5. Bypass semantici: uso di whitespace insoliti, commenti, separatori, nested encoding e frammentazione del token.

Il WAF deve essere allenato su queste famiglie, non solo su esempi statici. Un set di test serio deve includere varianti e non solo il payload canonico.

Normalizzazione: il punto in cui molti WAF falliscono

Prima di applicare regole, il traffico va normalizzato. Questo significa decodificare correttamente il contenuto senza introdurre ambiguità, unificare encoding equivalenti e ridurre i falsi negativi dovuti a rappresentazioni diverse dello stesso input.

Le normalizzazioni più importanti sono:

  • decoding URL una sola volta in modo controllato, con attenzione al double encoding;
  • decodifica HTML entity nel punto giusto della pipeline;
  • conversione in lowercase dove sensato;
  • compressione di spazi e separatori anomali;
  • rimozione di null byte e caratteri di controllo non necessari;
  • analisi dei parametri ripetuti e dei campi strutturati come JSON o XML.

Attenzione: normalizzare troppo aggressivamente può generare falsi positivi o alterare il significato del dato. Il punto non è “pulire” tutto, ma rendere confrontabile ciò che è semanticamente uguale.

Regole WAF efficaci contro XSS

Una buona politica WAF per XSS combina firme, pattern contestuali e punteggi di rischio. Le regole più utili non si limitano a bloccare tag HTML, ma osservano combinazioni sospette di elementi.

1. Bloccare le combinazioni ad alto rischio

È più utile rilevare la presenza combinata di delimitatori, attributi evento e protocolli pericolosi che inseguire una singola parola. Per esempio, la combinazione di apertura di tag, attributo dinamico e handler JavaScript è molto più significativa di un token isolato.

2. Rilevare protocolli e schemi pericolosi

Un WAF deve controllare schemi come javascript:, data: e altre varianti utilizzabili in link, immagini, iframe e redirect. Va considerata anche la rappresentazione encodeata o spezzata del protocollo.

3. Limitare gli attributi pericolosi

Gli handler HTML come onerror, onclick, onload e simili sono indicatori forti quando compaiono in input utente. In molte applicazioni non dovrebbero mai essere accettati.

4. Guardare gli oggetti strutturati

Se l’applicazione riceve JSON, XML o form complessi, il WAF deve analizzare i singoli campi e non trattare tutto come testo piatto. Molti bypass nascono quando un parser applicativo interpreta un valore in modo diverso dal WAF.

Una regola utile non è “blocca tutto ciò che assomiglia a HTML”, ma “blocca ciò che non dovrebbe essere presente in quel punto del flusso”.

Whitelist di contesto: la difesa più sottovalutata

Il modo più robusto per difendersi dall’XSS è ridurre ciò che l’applicazione accetta. Se un campo deve contenere solo nome e cognome, non ha senso permettere parentesi angolari, apici, slash, attributi o markup. Se un parametro deve contenere un ID numerico, il WAF può imporre formato stretto.

La whitelist di contesto funziona meglio della blacklist perché definisce il comportamento atteso. Esempi pratici:

  • campi numerici: solo cifre, eventualmente segno o separatori definiti;
  • email: formato email reale, non testo libero;
  • slug: caratteri limitati e prevedibili;
  • campi HTML consentiti: solo tramite sanitizzazione server-side con allowlist di tag e attributi;
  • URL: schemi consentiti e domini controllati.

Se il WAF supporta policy per endpoint, questa è una delle difese con il miglior rapporto tra efficacia e stabilità. Il traffico che non rispetta il formato previsto deve essere respinto o almeno messo in challenge.

Protezione contro bypass basati su encoding e frammentazione

Molti attaccanti non provano a inserire un payload leggibile. Usano frammenti spezzati, encoding misto e concatenazioni per superare regex ingenue. Il WAF deve quindi analizzare la richiesta più volte: raw, decoded e canonicalizzata.

Controlli pratici:

  • rilevare doppio encoding sospetto in parametri sensibili;
  • bloccare sequenze che cambiano significato dopo una seconda decodifica;
  • identificare frammenti HTML distribuiti su più parametri o campi;
  • analizzare separatori insoliti e whitespace non standard;
  • trattare con cautela i payload che diventano pericolosi solo dopo concatenazione lato applicazione.

Un errore frequente è fidarsi della prima decodifica. Se l’applicazione applica una seconda trasformazione, il WAF deve intercettare l’anomalia prima del rendering.

Gestione delle varianti HTML, SVG e contesti speciali

Molti WAF si concentrano sull’HTML classico e trascurano SVG, MathML, iframe, object, embed e contesti misti. È proprio qui che entrano in gioco payload moderni e meno ovvi.

La strategia migliore è:

  1. ridurre o bloccare i contenuti ricchi dove non necessari;
  2. sanitizzare con allowlist stretta se il contenuto HTML è davvero richiesto;
  3. vietare elementi e attributi che possono eseguire codice o caricare risorse attive;
  4. considerare i browser moderni e i loro comportamenti di parsing, non solo il testo raw.

Se il sito consente contenuti generati dagli utenti, il WAF da solo non basta. Deve lavorare insieme a sanitizzazione server-side, escaping contestuale e policy browser come Content Security Policy.

Integrare il WAF con CSP e output encoding

Il WAF non deve essere l’unica linea di difesa. Il miglior risultato si ottiene quando il filtro perimetrale è affiancato da una CSP ben progettata e da un encoding corretto in output.

Una CSP efficace può ridurre drasticamente l’impatto di un eventuale bypass del WAF. In particolare aiuta a limitare script inline, sorgenti esterne non autorizzate, plugin obsoleti e comportamenti dinamici pericolosi. Se il WAF lascia passare un payload, la CSP può ancora impedire l’esecuzione in molti casi.

Allo stesso modo, l’output encoding lato applicazione rimane fondamentale: il WAF intercetta il traffico sospetto, ma l’applicazione deve evitare di riflettere input non fidato nel DOM o nell’HTML senza escaping corretto.

Regole comportamentali e scoring

Le regole migliori non sono sempre binarie. Un sistema di scoring riduce i falsi positivi e aumenta la qualità del blocco. Per esempio, un parametro con un solo elemento sospetto può generare alert; la presenza di più indicatori coerenti può portare al blocco.

Indicatori utili per lo scoring:

  • numero di caratteri speciali in un campo che normalmente è semplice testo;
  • presenza di markup o pseudo-markup in parametri non destinati a HTML;
  • richieste con encoding ripetuto o incoerente;
  • user agent, pattern di frequenza e ripetizione anomala;
  • tentativi seriali su più endpoint con la stessa struttura di payload.

Questo approccio è più resiliente di una blacklist rigida, perché non dipende da una singola firma e si adatta meglio ai bypass evolutivi.

Testing: come verificare davvero il WAF

Un WAF non va considerato sicuro finché non è testato con payload realistici e varianti. Il test deve includere casi positivi, negativi e borderline.

Una batteria minima di verifica dovrebbe controllare:

  1. payload semplici che devono essere bloccati;
  2. payload encodeati che devono essere normalizzati e bloccati;
  3. payload frammentati che devono aumentare il punteggio o essere respinti;
  4. input legittimi che non devono generare falsi positivi;
  5. contenuti HTML consentiti che devono passare solo se sanitizzati correttamente.

È utile mantenere un set di richieste di test versionato, eseguito dopo ogni modifica alle regole. Senza regressione test, il WAF tende a degradare: o diventa troppo permissivo, o blocca troppo.

Manutenzione continua delle regole

Le regole WAF non sono statiche. I payload cambiano, le applicazioni evolvono, i browser introducono nuove superfici e i falsi positivi emergono con i nuovi contenuti. Serve manutenzione continua.

Una routine sana comprende:

  • revisione periodica dei log WAF;
  • analisi degli alert più frequenti;
  • whitelist mirate per endpoint o campi specifici;
  • aggiornamento delle firme del vendor o del progetto open source;
  • verifica degli incidenti reali per trasformarli in nuove regole.

Se il WAF genera troppo rumore, gli operatori smettono di fidarsi degli alert. Se blocca troppo poco, diventa un orpello. Il punto giusto è un equilibrio misurato su dati reali.

Una configurazione pratica e sostenibile

La configurazione migliore per difendere un WAF dai payload XSS più insidiosi segue questa gerarchia:

  1. bloccare i contesti che non devono mai accettare markup o script-like input;
  2. normalizzare correttamente la richiesta prima del matching;
  3. usare regole contestuali e scoring, non solo blacklist;
  4. ridurre o proibire HTML ricco dove non strettamente necessario;
  5. affiancare il WAF con sanitizzazione server-side e CSP;
  6. monitorare i log e aggiornare le regole in base ai tentativi reali.

Questa impostazione è più solida di qualsiasi firma isolata perché difende contro l’evoluzione dei payload, non contro una singola variante.

Conclusione operativa

Un WAF difende bene dall’XSS quando smette di ragionare come un filtro di testo e inizia a ragionare come un controllore di contesto. I payload più insidiosi non si riconoscono solo dall’aspetto, ma dal percorso che compiono tra encoding, parsing e rendering. Per questo la difesa efficace nasce da normalizzazione, whitelist, regole contestuali, scoring, CSP e verifiche continue.

Se il tuo obiettivo è ridurre davvero il rischio, la domanda giusta non è “come blocco questa stringa?”, ma “in quale contesto questa stringa non dovrebbe mai esistere?”. È lì che un WAF diventa utile sul serio.