Le Cross-Site Scripting, ou XSS, est une vulnérabilité ancienne qui figure régulièrement dans le top 10 de l’OWASP et qui reste présente dans une quantité non négligeable de projets en production. Elle permet à un attaquant de faire exécuter du code malveillant dans le navigateur d’autres utilisateurs.
Une attaque XSS se produit lorsqu’un attaquant parvient à injecter du code JavaScript malveillant dans une page web, puis à le faire exécuter dans le navigateur d’un autre utilisateur. Ce code peut voler des cookies de session, rediriger vers un faux site, afficher un faux formulaire de connexion, enregistrer les frappes clavier ou simplement afficher un message gênant. Les conséquences vont du simple embarras à la compromission d’un compte, puisqu’il peut servir à récupérer des mots de passe.
On distingue trois grandes formes. Dans le XSS réfléchi, la charge malveillante est contenue dans la requête elle-même, souvent dans l’URL, et renvoyée directement dans la réponse. La victime doit donc cliquer sur un lien spécialement forgé, un procédé souvent véhiculé par email ou par messagerie instantanée. La source juge qu’il n’est « pas très évolué ni extrêmement courant de nos jours », mais que, « quand ça passe, c’est simple et efficace ».
Le XSS stocké est présenté comme plus sérieux. Le code malveillant est enregistré dans la base de données, par exemple dans un commentaire, un pseudo, une bio ou un champ de formulaire, puis servi à tous les visiteurs de la page concernée. Sur un forum, chaque personne qui charge la page exécute le script, « sans le savoir ».
Le XSS basé sur le DOM ne met pas le serveur en cause. Le problème se situe côté navigateur : du JavaScript légitime de la page lit des données non fiables, comme les paramètres de l’URL, le localStorage ou postMessage, et les utilise sans les vérifier. La source illustre ce cas avec une page qui insère dans son contenu une valeur récupérée dans l’URL.
Pourquoi la faille persiste
D’après la source, le problème fondamental est la confiance. Les données venant de l’utilisateur, de la base de données ou d’une API tierce sont acceptées sans vérification, et un navigateur fait confiance à tout ce qu’une page lui envoie. Le texte relie aussi la question à la rétro-compatibilité, qui permet aux anciens sites de continuer à fonctionner, y compris ceux qui n’étaient pas équipés de protections bloquant par défaut les actions sensibles. Il rappelle enfin que toute donnée externe est potentiellement risquée : paramètres d’URL, champs de formulaire, en-têtes HTTP ou données stockées.
Les protections évoquées
Le principe numéro un est d’encoder les données avant de les afficher. En PHP, la fonction htmlspecialchars(), utilisée avec ENT_QUOTES et l’encodage UTF-8, convertit les caractères spéciaux HTML afin qu’ils s’affichent comme du texte et non comme du code. Pour une valeur placée dans une URL, la source recommande urlencode() plutôt que htmlspecialchars(). En JavaScript, textContent est présenté comme la règle la plus simple, car, contrairement à innerHTML, il n’interprète pas le HTML.
La Content Security Policy (CSP) ajoute une couche de protection, puisqu’elle indique au navigateur quels scripts il est autorisé à exécuter. Dans l’exemple de la source, seuls les scripts venant du domaine du site et d’un CDN autorisé sont acceptés. L’article prévient qu’une CSP bien configurée demande du temps, notamment pour les scripts inline et les ressources tierces, mais qu’elle reste « un excellent filet de sécurité ».
Enfin, les cookies peuvent être configurés avec l’attribut HttpOnly, qui les rend inaccessibles à JavaScript, Secure, qui limite leur transmission au HTTPS, et SameSite=Strict, qui les empêche d’être envoyés dans les requêtes cross-site. Selon la source, il ne s’agit pas d’une protection contre le XSS lui-même, mais ces attributs limitent considérablement l’impact d’une exploitation réussie.



