Les attaques XSS (Cross-Site Scripting) figurent parmi les vulnérabilités web les plus anciennes, répandues et dangereuses. Classée régulièrement dans le Top 10 de l’OWASP, cette faille permet à un attaquant d’injecter et d’exécuter du code malveillant dans le navigateur de vos utilisateurs. Cet article vous explique le mécanisme des failles XSS, leurs différentes formes, et surtout, les bonnes pratiques de sécurisation pour protéger votre application de manière efficace.
Qu’est-ce qu’une attaque XSS ? Le mécanisme de base
Une attaque XSS se produit lorsqu’une application web ne valide pas et n’échappe pas correctement les données fournies par les utilisateurs avant de les inclure dans ses pages. Cela permet à un attaquant d’injecter des scripts malveillants (généralement en JavaScript) qui seront exécutés par le navigateur des victimes.
Le scénario classique est le suivant :
-
Un attaquant repère un champ de saisie (commentaire, profil, formulaire de contact) où l’input est réaffiché sur la page sans filtrage.
-
Il y soumet un script malveillant (ex:
<script>alert('XSS')</script>). -
La victime visite la page légitime où ce contenu est affiché.
-
Le navigateur de la victime exécute le script comme s’il provenait du site de confiance, car il ne fait pas la différence.
-
Le script peut alors voler les cookies de session, hijacker la session, modifier le contenu de la page, ou rediriger l’utilisateur vers un site phishing.
Les trois grands types d’attaques XSS

1. XSS Réfléchi (Reflected XSS)
C’est la forme la plus simple. Le script malveillant est « réfléchi » immédiatement par le serveur, souvent via un paramètre dans l’URL. L’attaque nécessite que la victime clique sur un lien piégé.
Exemple :https://site-vulnérable.com/search?q=<script>alert(document.cookie)</script>
Cette attaque est souvent utilisée dans des campagnes de phishing par email. Pour des détails supplémentaires, cliquez ici.
2. XSS Stocké (Persistent ou Stored XSS)
Beaucoup plus dangereux. Le script malveillant est stocké du côté serveur (dans une base de données, un commentaire, un forum) puis réaffiché à chaque visite de la page infectée. Tous les utilisateurs visualisant cette page sont impactés. C’est une contamination à grande échelle.
Exemple : Un attaquant poste un commentaire sur un blog contenant un script qui vole les sessions. Tous les futurs lecteurs du blog exécuteront ce script.
3. XSS basé sur le DOM (DOM-based XSS)
Ici, la vulnérabilité ne se situe pas dans le code serveur, mais dans le code JavaScript côté client. Le script malveillant est injecté via une manipulation du DOM (Document Object Model) par du JavaScript non sécurisé qui utilise des sources contrôlables par l’utilisateur (comme document.location.hash ou window.name).
Exemple :
// Code vulnérable var userInput = window.location.hash.substring(1); document.getElementById("message").innerHTML = userInput;
Un attaquant pourrait créer l’URL : https://site.com/#<img src=x onerror=stealCookies()>
Les conséquences graves des failles XSS
Les impacts d’une exploitation réussie sont majeurs :
-
Vol de session : L’attaquant peut dérober les cookies de session et usurper l’identité de la victime.
-
Défacement : Modification de l’apparence du site web.
-
Keylogging : Enregistrement des frappes au clavier de l’utilisateur sur la page.
-
Propagation de malware : Redirection vers des sites exploitant des vulnérabilités navigateur.
-
Attaques côté client : Lancement d’attaques CSRF (Cross-Site Request Forgery) depuis le navigateur de la victime.
-
Atteinte à la réputation : Perte de confiance des utilisateurs et impact juridique (notamment au regard du RGPD en cas de fuite de données).
Comment bloquer les attaques XSS ? La défense en profondeur
La mitigation des failles XSS repose sur une stratégie de défense en couches (defense in depth).
1. Échappement des données (Output Encoding) – La règle d’or
C’est la mesure la plus critique. Il faut systématiquement échapper (encode) les données avant de les insérer dans différents contextes de la page. N’encodez jamais pour un contexte supposé « sûr ».
-
Contexte HTML : Remplacez
<,>,&,",'par leurs entités HTML (<,>, etc.). Utilisez les fonctions dédiées de votre framework (htmlspecialcharsen PHP,escapeen Django, JSX le fait automatiquement dans React). -
Contexte d’attribut HTML : Utilisez l’encodage pour les guillemets.
-
Contexte JavaScript : Échappez les sauts de ligne et les guillemets.
-
Contexte d’URL : Utilisez l’encodage URL (
encodeURIComponenten JS).
2. Validation des entrées (Input Validation)
Traitez toutes les données utilisateur comme non fiables. Appliquez une validation stricte en fonction du type de données attendu (format, longueur, jeu de caractères). Cette mesure complète l’échappement mais ne le remplace pas.
-
Liste blanche (Whitelisting) : Autorisez uniquement certains caractères ou patterns connus comme sûrs.
-
Rejet des données suspectes : Filtrez ou rejetez toute entrée contenant des balises HTML ou JavaScript.
3. Utilisation de politiques de sécurité : CSP (Content Security Policy)
CSP est un en-tête HTTP puissant (Content-Security-Policy) qui constitue une ligne de défense ultime. Il permet de restreindre les ressources (scripts, images, polices) que le navigateur est autorisé à charger ou exécuter.
-
Interdiction des scripts inline : Une politique stricte interdit l’exécution de scripts inline (
<script>...</script>) et d’attributs d’événement HTML (onclick,onerror), rendant la plupart des XSS inopérants. -
Restriction des sources : Autorisez les scripts uniquement depuis des domaines de confiance spécifiques (votre CDN, vos propres assets).
Exemple de CSP stricte :Content-Security-Policy: default-src 'self'; script-src 'self' https://trusted.cdn.com;
4. Protection des cookies avec les attributs HttpOnly et Secure
Marquez vos cookies de session avec l’attribut HttpOnly. Cela empêche leur accès via JavaScript (document.cookie), bloquant ainsi leur vol en cas de faille XSS. Couplez cela avec l’attribut Secure pour une transmission uniquement en HTTPS.Set-Cookie: sessionId=abc123; HttpOnly; Secure; SameSite=Strict
5. Encodage et filtrage côté serveur uniquement
Ne tentez jamais de « nettoyer » du HTML côté client (avec JavaScript) avant de l’envoyer au serveur. Un attaquant peut contourner cette défense. Toute logique de sécurité doit être implémentée côté serveur.
Une vigilance de tous les instants
Les attaques XSS exploitent la confiance fondamentale du navigateur envers le serveur. Les bloquer efficacement nécessite une hygiène de développement rigoureuse et une combinaison de techniques.
Adoptez une mentalité de sécurité dès la conception :
-
Échappez systématiquement les sorties en fonction de leur contexte.
-
Validez strictement toutes les entrées utilisateur.
-
Implémentez une CSP stricte comme barrière de dernier recours.
-
Protégez vos cookies avec
HttpOnlyetSecure. -
Utilisez des frameworks modernes (React, Angular, Vue) qui, par conception, encouragent ou imposent un échappement par défaut, mais restez vigilants sur leurs éventuels contournements (comme
dangerouslySetInnerHTML).
Intégrez des tests de sécurité automatisés (SAST, DAST) et des revues de code axées sur la sécurité dans votre cycle de développement. La sécurité n’est pas une fonctionnalité qu’on ajoute, mais un état d’esprit à cultiver à chaque ligne de code.