Il cross-site scripting è una vulnerabilità delle applicazioni web che consente di far eseguire codice non previsto dentro il browser di chi visita una pagina legittima. Il difetto non sta nel browser né nell’utente: sta nell’applicazione, che accetta un contenuto proveniente dall’esterno e lo restituisce nella pagina senza neutralizzarlo.

È una delle vulnerabilità più longeve del web e continua a comparire nelle classifiche OWASP, nonostante le contromisure siano note da vent’anni. La ragione è che le difese funzionano quasi sempre per impostazione predefinita nei framework attuali, e quindi il problema si concentra proprio nei punti in cui quella protezione viene aggirata.

  1. Come nasce la vulnerabilità
  2. Le tre tipologie di cross-site scripting
  3. Cosa comporta per un’azienda
  4. Perché i framework moderni hanno cambiato il quadro
  5. Le difese che funzionano
  6. Perché gli scanner automatici non trovano tutto
xss

Come nasce la vulnerabilità

Ogni applicazione web riceve dati dall’esterno e li rimanda a schermo: il nome inserito in un modulo, un parametro nell’indirizzo, il contenuto di un commento, il risultato di una ricerca. Il browser che riceve la pagina non ha modo di sapere quale parte del contenuto provenga dagli sviluppatori e quale da un visitatore: esegue ciò che trova.

Il cross-site scripting nasce quando un dato di provenienza esterna arriva nella pagina in una posizione dove il browser lo interpreta come istruzione invece che come testo. Il problema non è l’input in sé, ma il contesto in cui viene restituito: lo stesso contenuto è innocuo dentro un paragrafo e pericoloso dentro un attributo di tag o all’interno di uno script.

Questa è anche la ragione per cui la vulnerabilità sopravvive alle riscritture. Un’applicazione può gestire correttamente novantanove punti di uscita e sbagliarne uno, e quell’uno è sufficiente. Nella classificazione OWASP il cross-site scripting è ricondotto alla famiglia dell’injection, che raccoglie tutte le vulnerabilità in cui un dato viene interpretato come codice.

Le tre tipologie di cross-site scripting

La distinzione riguarda il percorso che il contenuto compie prima di arrivare nel browser, e determina quanto è difficile individuare il problema.

TipoDa dove arriva il contenutoChi viene colpitoDifficoltà di rilevamento
RiflessoDalla singola richiesta, di norma da un indirizzo costruito ad arteSolo chi apre quel collegamento, quindi serve indurre la vittima a farloBassa: è la forma che gli strumenti automatici individuano meglio
PersistenteDall’archivio dell’applicazione, dove è stato salvato in precedenzaChiunque apra quella pagina, senza bisogno di alcun collegamentoMedia, e alta se il contenuto è visibile solo a un’area riservata
Basato su DOMNon transita dal server: è il codice lato browser che lo elaboraChi apre la pagina nelle condizioni previste dall’attaccoAlta: non è visibile nella risposta del server e sfugge alle scansioni classiche

La forma persistente è la più grave in termini di conseguenze, perché non richiede che nessuno clicchi nulla. La forma basata su DOM è la più insidiosa in termini di individuazione: poiché non lascia traccia nella risposta del server, uno strumento che analizza soltanto ciò che il server restituisce non la vede.

Cosa comporta per un’azienda

L’errore ricorrente nel valutare questa vulnerabilità è considerarla un problema del singolo visitatore. Le conseguenze reali riguardano invece l’organizzazione che gestisce l’applicazione.

Il primo effetto è il furto della sessione. Con un token di sessione un attaccante entra nell’applicazione con l’identità della vittima, senza conoscerne la password e senza incontrare il secondo fattore di autenticazione, perché quel controllo è già stato superato dall’utente legittimo. Se la vittima ha un profilo amministrativo, l’accesso ottenuto è amministrativo.

Il secondo effetto è la modifica di ciò che gli utenti vedono. Un contenuto alterato all’interno di un portale aziendale, di un’area riservata ai clienti o di un sito istituzionale può veicolare richieste di credenziali che appaiono provenire da voi. La firma della vostra azienda è ciò che rende credibile la richiesta, ed è la ragione per cui questa vulnerabilità produce un danno di reputazione superiore al danno tecnico.

Il terzo effetto riguarda i dati. Le applicazioni web attuali eseguono nel browser una parte rilevante della logica, e ciò che è accessibile a quel codice diventa accessibile al codice iniettato: contenuti visualizzati, dati precaricati, informazioni presenti nell’archiviazione locale del browser.

Il cross-site scripting è una delle categorie verificate in un web vulnerability assessment, insieme alle altre voci della classificazione OWASP e alle configurazioni errate lato server. La verifica riguarda i punti in cui un contenuto esterno raggiunge la pagina, che nelle applicazioni con anni di sviluppo alle spalle sono più numerosi di quanto risulti dalla documentazione.

Perché i framework moderni hanno cambiato il quadro

Questa è la parte che distingue la situazione attuale da quella di dieci anni fa. I principali strumenti di sviluppo front-end oggi in uso — React, Angular, Vue — applicano la neutralizzazione dei contenuti per impostazione predefinita: un dato inserito nel modo consueto viene restituito come testo, non come istruzione, senza che lo sviluppatore debba occuparsene.

Il risultato è che nelle applicazioni costruite con questi strumenti la vulnerabilità non si presenta più in modo diffuso, ma si concentra in un numero ridotto di punti specifici. Sono quattro.

Il primo sono le funzioni che i framework stessi mettono a disposizione per inserire contenuto HTML grezzo, aggirando deliberatamente la protezione. Servono quando è necessario mostrare testo formattato, per esempio contenuti provenienti da un editor o da un sistema di gestione dei contenuti, e chi le usa si assume la responsabilità di sanificare il dato prima.

Il secondo sono i valori inseriti in contesti che non sono testo: un indirizzo dentro un collegamento, un parametro dentro un attributo, un dato dentro un blocco di codice eseguibile. La neutralizzazione predefinita agisce sul contesto testuale, e in quelli diversi le regole cambiano.

Il terzo è il codice che manipola direttamente la struttura della pagina lato browser, dove il framework non interviene. È l’origine della forma basata su DOM, e ricorre nelle porzioni di codice più vecchie o scritte fuori dalle convenzioni del framework.

Il quarto sono le librerie di terze parti. Un componente esterno che inserisce contenuto nella pagina introduce i propri difetti, e nessuna revisione del codice proprio li rileva: è la stessa dinamica delle vulnerabilità che risiedono nelle dipendenze esterne anziché nel codice dell’applicazione.

C’è poi la parte di applicazioni che non usa framework moderni. I portali gestionali interni, gli strumenti sviluppati anni fa e mai riscritti, le aree amministrative che nessuno tocca perché funzionano: lì la protezione predefinita non esiste, e la superficie resta quella di dieci anni fa.

Le difese che funzionano

Le contromisure si dispongono su livelli, e la ragione per usarle insieme è che ciascuna copre ciò che le altre lasciano scoperto.

MisuraCosa faCosa non copre
Neutralizzazione in uscita, adeguata al contestoÈ la difesa risolutiva: il dato viene restituito come testo e non come istruzioneI punti in cui è stata volutamente aggirata per mostrare contenuto formattato
Sanificazione con librerie dedicateConsente di mostrare testo formattato mantenendo solo i tag ammessiNulla, se la libreria è aggiornata; molto, se è stata scritta in casa
Content Security PolicyLimita quali script il browser è autorizzato a eseguire, riducendo l’effetto di una falla presenteNon corregge la vulnerabilità, e una policy troppo permissiva non protegge affatto
Attributi HttpOnly e SameSite sui cookieImpediscono che il token di sessione sia leggibile dal codice nella paginaLe azioni compiute dal codice iniettato con la sessione già aperta
Validazione in ingressoRiduce la superficie scartando in partenza i dati che non rispettano il formato attesoNon sostituisce la neutralizzazione in uscita, e da sola non è sufficiente
Web application firewallIntercetta i tentativi più comuni e riconoscibili prima che raggiungano l’applicazioneLe varianti costruite per aggirarlo, e la forma basata su DOM, che non transita dal server

Sull’ultima riga vale una precisazione, perché genera equivoci. Un firewall applicativo è una mitigazione utile e in alcune situazioni indispensabile, per esempio quando una correzione richiede tempo. Non è però una correzione: la vulnerabilità resta nell’applicazione, e la protezione dipende dalla capacità del filtro di riconoscere una forma che non ha ancora visto.

Resta la parte organizzativa. Chi sviluppa deve sapere quali funzioni aggirano la protezione predefinita e in quali condizioni possono essere usate: è materia di formazione tecnica, non di buone intenzioni, ed è l’unico livello che agisce prima che il difetto entri nel codice.

Perché gli scanner automatici non trovano tutto

Gli strumenti automatici individuano bene la forma riflessa, dove il contenuto inviato ricompare nella risposta e la corrispondenza è verificabile in modo meccanico. Sulle altre due forme il rendimento cala, per tre ragioni concrete.

La forma basata su DOM non transita dal server, quindi uno strumento che confronta richieste e risposte non ha nulla da confrontare: serve interpretare il codice eseguito nel browser, che è quello che fa un’analisi dinamica sull’applicazione in esecuzione.

La forma persistente richiede di raggiungere la pagina in cui il contenuto salvato viene mostrato, e non sempre è la stessa in cui è stato inserito. Se la visualizzazione avviene in un’area amministrativa, una scansione senza credenziali si ferma alla pagina di accesso e non arriva mai a vederla.

E resta il contesto. Uno strumento verifica se un valore compare nella pagina, ma stabilire se in quella specifica posizione sia effettivamente sfruttabile richiede una valutazione che l’automatismo non compie: è il motivo per cui i risultati vanno validati, e la ragione per cui un elenco di segnalazioni contiene sempre anche falsi positivi.

Quando le applicazioni hanno aree riservate, logiche di autorizzazione e contenuti generati dagli utenti, la verifica pertinente è il web application penetration test. L’analisi è condotta da un analista con credenziali e perimetro concordati, e arriva dove una scansione automatica non entra: le sezioni autenticate, i percorsi che richiedono più passaggi, le concatenazioni fra vulnerabilità che prese singolarmente sembrano irrilevanti.


    Dichiaro di aver letto e compreso l'Informativa sul trattamento dei dati