Rappel théorique

Le Cross-Site Scripting (XSS) permet à un attaquant d'injecter du code (le plus souvent JavaScript) qui s'exécute dans le navigateur d'un autre utilisateur, dans le contexte de sécurité du site visé. Cela permet de voler des cookies de session, de modifier la page (défacement), de rediriger l'utilisateur ou d'agir en son nom.

Trois familles de XSS

TypeDescriptionExemple
Réfléchi (reflected) La donnée malveillante provient de la requête (paramètre GET/POST) et est renvoyée immédiatement dans la réponse, sans échappement. recherche.php?q=<script>alert(1)</script>
Stocké (stored) La donnée malveillante est enregistrée côté serveur (base de données, fichier) puis affichée, sans échappement, à d'autres utilisateurs. Un commentaire contenant <script>...</script>, exécuté pour chaque visiteur qui consulte la page.
DOM-based Du code JavaScript côté client insère une donnée non fiable directement dans le DOM (innerHTML) sans passer par le serveur. document.getElementById('out').innerHTML = location.hash;

Mesures de protection

Démo 1 : XSS réfléchi

Un champ de recherche dont la valeur est ré-affichée dans la page ("Vous avez recherché : ...").

Démo vulnérable

La valeur est insérée directement dans le HTML, sans échappement.

Démo sécurisée

htmlspecialchars() + en-tête Content-Security-Policy.

Démo 2 : XSS stocké

Un mur de commentaires (table commentaires) : un commentaire malveillant posté une fois est ensuite exécuté pour chaque visiteur qui consulte la page.

Démo vulnérable

Les commentaires sont affichés sans échappement.

Démo sécurisée

Les commentaires sont affichés avec htmlspecialchars().

Démo 3 : XSS DOM-based

Page statique illustrant la différence entre innerHTML (dangereux avec une entrée non fiable) et textContent (sûr).

Accéder à la démo DOM-based