Glossario · Sicurezza
Cross-site scripting (XSS)
In inglese: Cross-site scripting
Detto anche: XSS, cross site scripting, XSS stored, XSS reflected
Definizione
L'XSS è una vulnerabilità in cui un input non attendibile viene eseguito come script nel browser di un altro utente, permettendo a un attaccante di agire al suo posto.
Il cross-site scripting (XSS) si verifica quando un’applicazione prende l’input di un utente e lo inserisce in una pagina senza un encoding adeguato, così che il browser lo tratta come HTML o JavaScript invece che come testo. Lo script viene quindi eseguito con la sessione della vittima sul sito vulnerabile: può leggere i dati della pagina, fare richieste a nome dell’utente o cambiare ciò che vede. Nella OWASP Top 10 2021 rientra nella categoria A03 Injection.
I tre tipi
- Stored (persistente). Il payload viene salvato (un commento, un nome di profilo, un ticket di supporto) e servito a chiunque lo visualizzi. Di solito è il più grave.
- Reflected (riflesso). Il payload si trova nella richiesta, spesso in un parametro dell’URL come un termine di ricerca, e viene rimandato indietro così com’è nella risposta.
- DOM-based. Il JavaScript lato client legge dati controllati dall’attaccante (per esempio
location.hash) e li scrive nella pagina tramite un sink non sicuro comeinnerHTML.
Cosa verifica un tester
Inserisci un marcatore innocuo in ogni campo che viene poi visualizzato (a te, ad altri utenti, agli amministratori in un back office) e controlla se torna indietro come testo o come markup attivo. Un controllo automatizzato in Playwright, solo per test autorizzati:
import { test, expect } from '@playwright/test';
test('comment body is rendered as text, not HTML', async ({ page }) => {
const probe = '<img src=x onerror="window.__xssProbe=1">';
await page.goto('/posts/1');
await page.getByLabel('Comment').fill(probe);
await page.getByRole('button', { name: 'Post comment' }).click();
// Escaped output shows the literal characters on screen
await expect(page.getByText(probe)).toBeVisible();
// and the handler never ran
expect(await page.evaluate(() => (window as any).__xssProbe)).toBeUndefined();
});
Controlla anche contesti di output diversi dal semplice HTML: valori dentro attributi, dentro script inline, negli URL (link javascript:) e negli editor di testo formattato, perché ognuno richiede un encoding diverso.
Difese da verificare
- Encoding dell’output di default. I framework moderni (React, Angular, Vue) eseguono automaticamente l’escape del testo; cerca le “vie di fuga” come
dangerouslySetInnerHTML,v-htmloinnerHTML. - Sanitizzazione dell’HTML per le funzionalità che accettano davvero del markup.
- Un header Content Security Policy che blocchi gli script inline, come secondo livello di difesa.
- Cookie di sessione
HttpOnly, così che un XSS riuscito non possa semplicemente leggere il cookie di sessione.
Non eseguire mai test su sistemi che non sono tuoi o per cui non hai un’autorizzazione scritta.