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
| Type | Description | Exemple |
|---|---|---|
| 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
- Échapper les sorties selon leur contexte :
htmlspecialchars()pour du texte HTML, encodage spécifique pour les attributs, le JavaScript ou les URL. - Valider/filtrer les entrées (longueur, format attendu).
- Content-Security-Policy (CSP) : limite les sources de scripts autorisées, réduit l'impact d'une injection malgré tout.
- Cookies de session : attributs
HttpOnly,SecureetSameSite. - Côté client, préférer
textContentàinnerHTMLpour insérer des données non fiables.
Démo 1 : XSS réfléchi
Un champ de recherche dont la valeur est ré-affichée dans la page ("Vous avez recherché : ...").
La valeur est insérée directement dans le HTML, sans échappement.
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.
Les commentaires sont affichés sans échappement.
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).