Le Cross-Site Scripting (XSS) permet aux attaquants d'injecter du JavaScript malveillant dans les pages web chargées par d'autres utilisateurs.
TL;DR
Le Cross-Site Scripting (XSS) est une vulnérabilité d'injection côté client (CWE-79, OWASP A03:2021) où un attaquant injecte du JavaScript malveillant dans une page web servie à d'autres utilisateurs. Le code injecté s'exécute dans le navigateur de la victime sous l'origine du site vulnérable, héritant de tous ses privilèges : cookies, tokens localStorage, accès au DOM et capacité d'effectuer des requêtes authentifiées au nom de la victime.
Le XSS est la classe de vulnérabilité côté client la plus répandue sur le web. CWE-79 s'est classé #1 dans les CWE Top 25 de 2024 et 2025, et environ 20 % de tous les rapports HackerOne valides concernent des XSS. L'étendue de sévérité est large : un XSS réfléchi sur un champ de recherche est CVSS 6.1, tandis qu'un XSS stocké se déclenchant dans le tableau de bord d'un administrateur peut atteindre CVSS 9.3 Critique.
Ce qui rend le XSS particulièrement dangereux, c'est la combinaison de son omniprésence et de l'étendue de son impact. Le vol de session, la collecte d'identifiants, la livraison de malware, la manipulation du DOM et l'amplification de CSRF sont tous réalisables via une seule vulnérabilité XSS.
| Variante | Persistance | Cible de l'attaque | Détection | CVSS typique |
|---|---|---|---|---|
| Réfléchi | Aucune — dans l'URL | Navigateur de la victime | Scanner côté serveur | 6.1 |
| Stocké | Base de données / fichiers | Tous les visiteurs | Canary écriture + lecture | 7.2–9.3 |
| Basé sur le DOM | Aucune — côté client | Navigateur de la victime | Suivi de contamination sans tête | 6.1–8.8 |
| À l'aveugle | Backend / logs | Panneaux d'administration | Callback OOB avec token | 8.5–9.1 |
| Mutation (mXSS) | Variable | Consommateurs du sanitizer | Parsing différentiel | 6.1–9.0 |
Toutes les variantes de XSS partagent le même flux fondamental : des données contrôlées par l'attaquant atteignent un contexte de rendu du navigateur sans sanitization ni encodage correct.
Une fois exécuté dans le navigateur de la victime, un payload XSS peut :
document.cookie (non-HttpOnly) et l'envoyer à l'attaquantlocalStorage.getItem('access_token') et l'exfiltrerfetch() depuis le navigateur admin vers des API internes (XSS à l'aveugle combiné + SSRF)unsafe-inline dans script-src, neutralisant toutes les protections nonce/hash (HTTP Archive / Flatt Security Research 2024)Referer, User-Agent), champs JSON rendus en HTML, métadonnées de fichiersxsstest"'<> et inspecter le corps brut de la réponseBreachVex détecte le XSS dans les cinq classes de variantes via une approche en deux passes : réflexion de canary avec classification du contexte suivie d'une injection de payload adaptée au contexte, avec confirmation d'exécution dans un vrai navigateur et callbacks de token hors-bande.
Encoder au niveau du contexte d'injection exact. Le contexte détermine le schéma d'encodage :
from markupsafe import escape
import json
from urllib.parse import quote
# Contexte corps HTML / attribut
safe_html = escape(user_input) # & " ' < > → entités HTML
# Contexte chaîne JavaScript (dans les balises <script>)
safe_js = json.dumps(user_input) # encadre entre guillemets, échappe les caractères spéciaux
# Contexte URL
safe_url = quote(user_input, safe='') # encode en pourcentage chaque caractère spécialUn CSP strict basé sur des nonces casse la plupart des exploits XSS même quand l'encodage est contourné :
Content-Security-Policy:
default-src 'none';
script-src 'nonce-ALEATOIRE_PAR_REQUETE' 'strict-dynamic';
object-src 'none';
base-uri 'none';
require-trusted-types-for 'script';'unsafe-inline' neutralise complètement les protections par nonce et hash. Tout CSP le contenant ne fournit aucune atténuation XSS significative. 91 % des en-têtes CSP déployés contiennent cette directive.
Les Trusted Types (appliquées sur YouTube, Microsoft 365 et Stripe depuis 2024) imposent que toutes les assignations aux sinks DOM passent par une politique définie par le développeur :
const policy = trustedTypes.createPolicy('default', {
createHTML: (input) => DOMPurify.sanitize(input),
});
element.innerHTML = policy.createHTML(userInput); // sûr — passe par le sanitizer
element.innerHTML = userInput; // lance une TypeError en mode enforcedActiver via CSP : require-trusted-types-for 'script'
Set-Cookie: session=abc123; HttpOnly; Secure; SameSite=StrictHttpOnly empêche le vol via document.cookie. SameSite=Strict prévient les chaînes CSRF issues des payloads XSS. Aucun des deux ne prévient le XSS lui-même — ils réduisent l'impact d'une exploitation réussie.
Le XSS est une vulnérabilité d'injection côté client où un attaquant injecte du JavaScript malveillant dans une page web servie à d'autres utilisateurs. Le script s'exécute dans le navigateur de la victime sous l'origine du site ciblé, héritant de ses cookies, tokens et accès au DOM.
Les cinq variantes principales sont : le XSS réfléchi (non persistant, nécessite que la victime clique sur un lien), le XSS stocké (persisté en base de données, se déclenche pour chaque visiteur), le XSS basé sur le DOM (côté client uniquement, la réponse serveur est propre), le XSS à l'aveugle (variante stockée qui se déclenche dans des panneaux d'administration invisibles pour l'attaquant), et le XSS par mutation (contourne les sanitizers via le re-parsing HTML du navigateur).
Le XSS stocké ciblant les panneaux d'administration atteint CVSS 9.3 (Critique) car il se déclenche automatiquement pour chaque administrateur authentifié sans nécessiter d'interaction au-delà du chargement de la page. Le XSS à l'aveugle partage cette sévérité pour la même raison.
Le XSS réfléchi et basé sur le DOM part d'un score de base CVSS 6.1 (CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N). Le XSS stocké ciblant des utilisateurs privilégiés atteint 9.3 (Scope : Changed, Confidentialité : High, Intégrité : High).
Le script injecté lit document.cookie et l'envoie vers un serveur contrôlé par l'attaquant via fetch() ou une astuce avec src d'img. Les cookies HttpOnly sont invisibles au JavaScript, mais le XSS peut quand même effectuer des requêtes authentifiées au nom de la victime et exfiltrer les tokens localStorage.
L'encodage de sortie prévient le XSS quand il est appliqué dans le bon contexte (corps HTML, attribut HTML, chaîne JavaScript, URL, CSS nécessitent chacun un encodage différent). Manquer le contexte ou encoder à l'entrée plutôt qu'à la sortie laisse des failles. Le CSP et les Trusted Types ajoutent des couches de défense indépendantes.
Le XSS représente environ 20 % de tous les rapports de vulnérabilité valides sur HackerOne, ce qui en fait la classe de vulnérabilité la plus signalée sur la plateforme.
Oui. 91 % des sites avec CSP incluent encore unsafe-inline dans script-src, neutralisant toutes les protections par nonce et hash. Même les CSP strictes peuvent être contournées via des endpoints JSONP, du DOM clobbering ou des gadgets de prototype pollution.