
💡 Cross-site scripting (XSS) : qu'est-ce que c'est et comment protéger votre site en 2026
En 2019, près de 75% des grandes entreprises ont été confrontées à du cross-site scripting. Sept ans plus tard, les failles XSS sont toujours là. Microsoft a signalé 970 cas de XSS clôturés depuis janvier 2024 seulement, et une vulnérabilité découverte en 2025 dans l’extension LiteSpeed Cache a mis 7 millions de sites WordPress en danger.
Le problème ne vient pas de la technologie. JavaScript, le langage du web interactif, alimente chaque thème, chaque formulaire de commentaire, chaque panier d’achat. Le problème, c’est qu’un attaquant peut forcer votre site à exécuter son code, et que le navigateur est incapable de distinguer un script malveillant d’un script légitime.
Décortiquons les mécanismes du XSS, les trois types d’attaques et les couches de protection spécifiques qui mettent votre site à l’abri du cross-site scripting. Avec des outils, des exemples de code et des cas réels sur WordPress.
💡 Aperçu rapide:
- Ce qu’est le XSS et comment un attaquant injecte du code malveillant dans un site de confiance
- Les trois types de cross-site scripting (stocké, reflété et basé sur le DOM) et leurs différences
- Mise en place pas à pas de trois couches de protection: WAF, échappement des sorties et Content Security Policy
- Où chercher les vulnérabilités XSS sur votre site et que faire si une attaque a déjà eu lieu
Qu’est-ce que le cross-site scripting

Le Cross-Site Scripting est une attaque par injection où un attaquant intègre un script malveillant dans une page d’un site de confiance. Le navigateur de la victime exécute ce code parce qu’il le considère comme faisant partie de la page légitime. D’où le nom: le script provient d’un franchissement de la frontière du site.
Techniquement, le vecteur d’attaque ne se limite pas à JavaScript. Des vulnérabilités sont possibles en HTML, Flash, ActiveX et CSS. Mais en pratique, la très grande majorité des exploits ciblent JS. La raison: l’accès à l’arbre DOM, aux cookies, au localStorage et la possibilité d’effectuer des requêtes pour le compte de l’utilisateur.
Sur WordPress, les vulnérabilités surviennent presque toujours via des extensions et des thèmes qui gèrent incorrectement les saisies utilisateur. Formulaires de commentaire, barres de recherche, formulaires de contact, pages de connexion: tout champ qui accepte des données et les réaffiche sans filtrage devient un point d’entrée. Selon Claranet, 2570 cas de XSS reflété et stocké ont été détectés dans des applications web testées en 2024.
Comment fonctionne le XSS
Un attaquant a besoin de deux conditions: un point d’entrée pour le code malveillant et une absence de filtrage à l’affichage. En pratique, cela s’obtient de deux manières: par la manipulation des saisies utilisateur et par le contournement de la same-origin policy.
Injection via les saisies utilisateur
Le scénario le plus courant. Un champ utilisateur (barre de recherche, formulaire de commentaire, champ d’envoi de fichier) accepte non seulement du texte, mais aussi du code exécutable. Si l’extension ou le thème n’échappe pas la sortie, un <script>alert('XSS')</script> saisi s’exécutera dans le navigateur de toute personne qui ouvre la page.
Le problème est plus profond qu’il n’y paraît. Même des développeurs expérimentés passent à côté de vecteurs XSS via des champs apparemment inoffensifs: l’envoi d’un fichier SVG contenant un script intégré, la saisie de données dans le champ «nom d’utilisateur» lors de l’inscription, les paramètres d’URL dans les redirections. Un seul champ sans esc_url() ou esc_attr(), et le site est exposé.
Dans un monde idéal, un champ de recherche accepte du texte brut et rien d’autre. Dans l’écosystème réel de WordPress avec plus de 60 000 extensions, cette garantie est inatteignable: une seule extension avec un echo $_GET['q'] sans esc_html() suffit.
Contournement de la same-origin policy

La same-origin policy est une règle de sécurité fondamentale des navigateurs: les scripts d’une origine ne peuvent pas lire les données d’une autre. Une page Facebook et une page bancaire ouvertes dans le même navigateur n’échangent pas d’informations. Mais cette règle a un talon d’Achille: les cookies de session.
Lorsque vous vous connectez à un site, le navigateur crée un cookie de session qui confirme votre identité à chaque requête. Sans lui, vous devriez saisir votre mot de passe à chaque nouvelle page consultée. Le problème, c’est que le navigateur attache ce cookie à toute requête vers le domaine, y compris les requêtes initiées par un script malveillant.
Schéma d’attaque: un attaquant trouve une vulnérabilité XSS sur example.com → injecte un script qui lit document.cookie → envoie le cookie de session vers son serveur. Résultat: un accès complet au compte de la victime sans connaître le mot de passe. Les cookies de session stockent les identifiants, le contenu du panier, les informations de livraison: tout le contexte utilisateur.
Les trois types d’attaques XSS

La classification des XSS repose sur l’endroit et la manière dont le code malveillant atteint la victime. Il en existe trois types, et protéger votre site exige d’en comprendre les mécanismes.
XSS stockée (type I)
Le type le plus dangereux. Le script malveillant est enregistré sur le serveur (dans la base de données, les logs, un champ de commentaire) et s’exécute à chaque ouverture de la page infectée. Sur WordPress, c’est un scénario classique: un attaquant laisse un commentaire contenant une balise <script>, le plugin de commentaires ne filtre pas le HTML, et le script se déclenche pour chaque visiteur de l’article.
La particularité de la XSS stockée est que l’attaque n’a pas besoin d’être activée via un lien de phishing. La victime se contente de visiter la page. En 2025, la vulnérabilité CVE-2025-12709 dans le plugin Interactions pour WordPress était un cas classique de XSS stockée due à une insuffisance de l’assainissement des entrées dans les sélecteurs d’événements.
XSS réfléchie (type II)
L’attaquant envoie à la victime un lien contenant du code malveillant dans les paramètres d’URL. Le serveur «réfléchit» ce code dans la réponse, par exemple dans un message d’erreur de recherche ou dans une ligne «Vous avez cherché: X». Le navigateur exécute le script parce qu’il est arrivé dans le corps de la réponse depuis un serveur de confiance.
La XSS réfléchie nécessite une action active de la victime: cliquer sur un lien. L’attaque est donc souvent déguisée en URL légitime dans un email de phishing. Sur WordPress, un vecteur typique est celui des plugins de recherche qui affichent la requête sans esc_html().
XSS basée sur le DOM (type 0)
Contrairement aux deux premières, ici la vulnérabilité ne se situe pas dans le code côté serveur mais dans le JavaScript côté client. Les données malveillantes ne vont jamais jusqu’au serveur; elles sont traitées directement dans le navigateur via des méthodes non sécurisées de l’API DOM telles que innerHTML, document.write() ou eval().
La source des données est l’URL (via window.location), document.referrer ou toute autre source contrôlable côté client. Les logs serveur sont propres; l’attaque n’est visible que dans le navigateur. Ce type de XSS est le plus difficile à détecter, car les WAF et les scanners côté serveur ne la voient pas.
Pourquoi la XSS est particulièrement dangereuse pour WordPress
WordPress est la cible numéro un pour la XSS pour une raison: l’écosystème. Sur les plus de 60 000 plugins du répertoire, tous ne font pas l’objet d’une revue stricte concernant l’échappement des sorties. Un seul plugin vulnérable compromet l’ensemble du site.
En septembre 2025, Microsoft a publié une analyse expliquant pourquoi la XSS reste une menace 25 ans après son apparition. Le principal enseignement: la complexité de la pile web moderne rend l’élimination complète de la XSS quasiment impossible, car il y a trop de couches où un échappement peut être oublié.
Ce qu’un attaquant obtient via une XSS sur WordPress:
- L’accès au panneau d’administration en volant les cookies de session de l’administrateur
- L’injection de liens cachés (spam SEO)
- Le téléchargement de logiciels malveillants sur les ordinateurs des visiteurs
- La substitution des coordonnées de paiement dans WooCommerce
- La défiguration massive des pages du site
Combinée à l’ingénierie sociale, la XSS devient un vecteur d’attaques sophistiquées: de l’installation de keyloggers à la falsification de requête intersites.
Comment protéger votre site contre les XSS: trois couches

La protection contre les XSS ne se résout pas par un seul réglage. Seule la défense en profondeur fonctionne: les plugins de sécurité bloquent les attaques grossières, l’échappement en sortie ferme les vecteurs techniques, et la Content Security Policy bloque l’exécution des scripts au niveau du navigateur.
Couche 1: plugins de sécurité et pare-feu
La première ligne de défense est un plugin WordPress doté d’un pare-feu applicatif web (WAF). Le WAF filtre les requêtes entrantes avant qu’elles n’atteignent le code des plugins et bloque les signatures d’attaques XSS connues.
Lorsque vous choisissez un plugin de sécurité, utilisez cette liste de contrôle:
- Analyse régulière des malwares et des CVE connues dans les plugins installés
- Pare-feu avec des règles pour bloquer les motifs XSS dans les requêtes
- Durcissement de WordPress: désactiver XML-RPC, changer le préfixe des tables, empêcher l’édition de fichiers depuis l’administration
- Gestion centralisée des mises à jour de tous les plugins et thèmes
- Sauvegarde, pour pouvoir restaurer le site si une attaque parvient à passer
Vous trouverez une sélection de plugins de sécurité WordPress avec des analyses détaillées des fonctionnalités de chaque outil dans des comparatifs spécialisés sur notre plateforme.
Couche 2: validation et échappement en sortie
C’est la principale ligne de défense technique. La règle est simple et non négociable: aucune donnée utilisateur n’est envoyée au navigateur sans échappement. WordPress fournit des fonctions natives pour cela, et chacune est liée à un contexte de sortie spécifique.
Boîte à outils de base pour les développeurs WordPress:
1 // For output inside HTML tags — between <p> and </p> 2 echo esc_html($user_input); 3 4 // For HTML attributes — inside value="..." 5 echo esc_attr($user_input); 6 7 // For URLs in href, src, and other attributes 8 echo esc_url($user_url); 9 10 // For output inside <textarea> 11 echo esc_textarea($user_text); 12 13 // For JavaScript variables 14 echo esc_js($user_data); 15 16 // For allowed HTML tags with dangerous attributes removed 17 echo wp_kses_post($user_html);
Le point clé: le choix de la fonction dépend du contexte. esc_html() dans un attribut href ne vous sauvera pas; l’attaquant insérera javascript:alert('XSS'). À l’inverse, esc_url() à l’intérieur d’un paragraphe laissera passer une balise <script>. Le contexte détermine la fonction.
wp_kses() mérite une mention spéciale: un filtre puissant qui n’autorise que les balises et attributs HTML autorisés. Pour le contenu utilisateur (commentaires, descriptions de profil, champs personnalisés), c’est le niveau de filtrage minimum requis.
Couche 3: Content Security Policy (CSP)
La CSP est un en-tête HTTP qui indique au navigateur: «Exécutez les scripts uniquement depuis ces sources.» C’est la dernière ligne de défense. Même si un attaquant a injecté une balise <script> dans la page, le navigateur ne l’exécutera pas car les scripts inline ne figurent pas sur la liste blanche.
Politique CSP de base pour WordPress:
1 // In functions.php or via a plugin 2 function add_csp_header() { 3 header("Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:;"); 4 } 5 add_action('send_headers', 'add_csp_header');
Une politique stricte ('strict-dynamic' au lieu de 'unsafe-inline') est plus sûre mais nécessite de configurer un nonce ou des hashs pour chaque script légitime. C’est un travail conséquent sur un site avec une dizaine de plugins actifs. Commencez par le mode rapport uniquement pour collecter les journaux de violation sans casser le frontend:
1 Content-Security-Policy-Report-Only: default-src 'self'; report-uri /csp-report-endpoint
La CSP ne remplace pas l’échappement. Elle atténue les conséquences des erreurs lorsque l’échappement a été oublié quelque part.
Vidéo: les XSS, des bases à l’exploitation
Pour voir les XSS en action et comprendre comment trouver des vulnérabilités sur de vrais sites, regardez cette analyse de 30 minutes:
Après l’avoir visionnée, revenez aux couches de protection ci-dessus. Elles prendront désormais tout leur sens au niveau mécanique, et pas seulement au niveau des noms de fonctions.
⁉️🤔 Foire aux questions
Mettre à jour WordPress et les plugins aide-t-il à se protéger contre les XSS?
Oui, et c’est l’étape de protection la plus sous-estimée. Chaque nouvelle version de plugin corrige souvent des CVE spécifiques, y compris des vulnérabilités XSS. La vulnérabilité LiteSpeed Cache CVE-2025-12450 a été corrigée dans la semaine suivant sa découverte, mais 7 millions de sites qui n’ont pas mis à jour sont restés exposés. Activez les mises à jour automatiques pour tous les plugins; les problèmes de compatibilité sont rares, alors qu’un correctif manqué frappe à coup sûr.
Un seul plugin de sécurité suffit-il à protéger contre les XSS?
Non. Un plugin de sécurité avec WAF bloque les signatures d’attaques connues mais ne voit pas les vulnérabilités zero-day ni les vecteurs non standard. Il doit constituer la première couche, suivie de l’échappement en sortie dans le code du thème et des en-têtes CSP. Trois couches ensemble offrent une protection qu’aucune d’elles ne peut fournir seule.
Comment vérifier si mon site présente des vulnérabilités XSS?
Commencez par un scanner gratuit: WPScan, Sucuri SiteCheck, Qualys SSL Labs. Pour des tests plus approfondis, utilisez OWASP ZAP (Zed Attack Proxy), un outil open source qui fuzze automatiquement les champs de saisie et détecte les XSS réfléchies. Important: les scanners automatisés ne voient pas les XSS basées sur le DOM; cela nécessite un audit manuel du code JavaScript du site.
Peut-on éliminer complètement les XSS sur un site de grande taille?
L’élimination complète des XSS sur un site avec des dizaines de plugins et un thème personnalisé est un objectif proche de l’idéal mais difficile à atteindre pleinement. Chaque nouveau plugin, chaque mise à jour de thème, chaque extrait personnalisé dans
functions.phpest un point d’entrée potentiel. Un objectif réaliste: trois couches de protection, des mises à jour automatiques, des audits trimestriels et une CSP en mode rapport uniquement. Vous intercepterez ainsi la grande majorité des attaques à un stade précoce.
Que dois-je faire si mon site a déjà été attaqué via une XSS?
Changez immédiatement tous les mots de passe et réinitialisez les clés de session dans
wp-config.phpà l’aide du générateur WordPress. Ensuite, restaurez le site à partir d’une sauvegarde propre. Après la restauration, installez un plugin de sécurité, mettez à jour tous les plugins et thèmes vers les dernières versions, et ajoutez un en-tête CSP dansfunctions.php. Les mots de passe doivent être changés car une XSS vole souvent les cookies de session de l’administrateur.
Les XSS et l’injection SQL sont-elles la même chose?
Non, bien que les deux soient des attaques par injection. L’injection SQL cible la base de données via une requête SQL; l’attaquant peut lire, modifier ou supprimer des tables. La XSS cible le navigateur de l’utilisateur via JavaScript; l’objectif est de voler des sessions, d’afficher des formulaires de phishing ou de modifier le contenu de la page. Elles ont des vecteurs différents, des fonctions de protection différentes (
$wpdb->prepare()pour SQL,esc_html()pour XSS) et des conséquences différentes. Mais en pratique, elles vont souvent de pair: la XSS est utilisée pour délivrer une injection SQL via le panneau d’administration.
Faut-il craindre les XSS en 2026
Les XSS n’ont pas disparu, mais s’en défendre est devenu une routine d’ingénierie, pas de la magie. Trois couches (un plugin avec WAF, l’échappement en sortie à tous les points de contact avec l’utilisateur et un en-tête CSP) ferment la grande majorité des vecteurs. Ajoutez à cela les mises à jour automatiques des plugins et des thèmes, pour que les correctifs arrivent avant les exploits.
Si vous n’utilisez actuellement aucune de ces couches, commencez par installer un plugin de sécurité et activez les mises à jour automatiques dans l’administration WordPress. Cela prend 10 minutes et ferme les points d’entrée les plus grossiers. Revenez ensuite à cet article lorsque vous serez prêt à mettre en œuvre l’échappement et la CSP.



