Comprendre XSS et protéger son application

Auteur : Publié le

En bref : XSS (Cross-Site Scripting) est une vulnérabilité qui conduit le navigateur à exécuter du code non fiable dans le contexte du site visité. Elle apparaît le plus souvent lorsque l’application traite les données de l’utilisateur comme un fragment de page ou de code, au lieu de les traiter comme du texte brut. Pour s’en protéger, il faut avant tout afficher les données de manière sûre, et pas seulement bloquer les saisies suspectes.

Comment fonctionne XSS et que peut faire un attaquant ?

Le navigateur interprète HTML comme la structure de la page et JavaScript comme des instructions à exécuter. Si l’application insère du contenu non vérifié à un endroit où il sera interprété comme du code, un attaquant peut modifier le comportement de la page chez un autre utilisateur. Ce contenu peut provenir d’un commentaire, d’un paramètre d’adresse, d’un nom de profil ou d’une réponse d’un service externe.

Le code exécuté par XSS agit dans le contexte du site attaqué. Il peut lire les données accessibles sur la page, modifier son contenu, afficher un faux formulaire de connexion ou effectuer des opérations avec les droits de l’utilisateur connecté. Les conséquences réelles dépendent des fonctionnalités de l’application et des protections en place.

Cela ne signifie pas automatiquement que le serveur ou l’ordinateur entier est compromis. Le problème concerne avant tout la confiance que le navigateur accorde au code exécuté par le site. Un utilisateur peut ouvrir une adresse légitime et malgré tout accéder à une page contenant du contenu malveillant.

Les trois formes de XSS les plus souvent décrites

Cette classification aide à déterminer l’origine du contenu dangereux et l’endroit où l’application le traite :

Ces catégories ne s’excluent pas toujours. « Stocké » et « réfléchi » décrivent surtout la manière dont les données sont acheminées, tandis que « DOM-based » indique où se produit le traitement dangereux. Un contenu conservé en base de données peut donc lui aussi provoquer un DOM-based XSS.

Exemple simple : du texte traité comme du HTML

Supposons que l’application affiche un nom d’utilisateur. N’exécutez l’exemple suivant que dans votre propre environnement de test ou dans un environnement pour lequel vous disposez d’une autorisation explicite :

const nom = '<img src="x" onerror="alert(\'Test XSS\')">';
const element = document.querySelector('#accueil');
element.innerHTML = nom;

La propriété innerHTML demande au navigateur d’interpréter la valeur comme du HTML. Si l’image ne se charge pas, le gestionnaire d’erreur peut déclencher alert, qui affiche une boîte de dialogue contenant un message. Cet exemple démontre l’exécution de code, pas un vol de données ; des protections supplémentaires du navigateur ou du site peuvent le bloquer.

Si le nom doit être affiché comme du texte brut, la bonne solution est la suivante :

const nom = '<img src="x" onerror="alert(\'Test XSS\')">';
const element = document.querySelector('#accueil');
element.textContent = nom;

La propriété textContent affichera la chaîne de caractères fournie sans créer d’image ni exécuter l’instruction qu’elle contient. La différence est fondamentale : les données restent des données. Il n’est pas nécessaire de deviner quels mots ou quelles balises pourraient être dangereux.

Comment protéger une application contre XSS

Adaptez la protection au contexte d’utilisation des données. L’encodage en sortie consiste à représenter les caractères spéciaux de manière à ce qu’ils ne soient pas interprétés comme des éléments de syntaxe. Les règles diffèrent selon qu’il s’agit de texte dans du HTML, d’une valeur d’attribut, d’une adresse URL ou d’un fragment de JavaScript. Remplacer uniquement les chevrons < et > ne protège pas toutes ces situations.

Pour afficher du texte brut, utilisez des mécanismes de modèles sécurisés et des interfaces telles que textContent. L’encodage automatique du framework est utile, mais une fonction qui insère du HTML brut peut le contourner. Ces exceptions nécessitent un contrôle distinct.

Si les utilisateurs ont réellement besoin de mise en forme HTML, utilisez une bibliothèque de nettoyage activement maintenue, comme DOMPurify. Ce nettoyage, aussi appelé sanitisation, supprime les éléments et attributs interdits selon des règles définies. Un filtre maison reposant sur quelques expressions régulières n’offre pas une protection équivalente.

La validation, qui consiste à vérifier que les données respectent le format autorisé, reste utile : un champ d’âge doit accepter un nombre, et l’adresse d’un lien doit utiliser un schéma autorisé. Elle ne remplace toutefois pas un affichage sécurisé. Protéger uniquement le formulaire ne suffit pas non plus, car les données peuvent entrer dans l’application par une autre voie.

Des couches de protection supplémentaires limitent les conséquences des erreurs. CSP (Content Security Policy) permet de définir des règles d’exécution des scripts, mais son efficacité dépend de sa configuration. L’attribut HttpOnly empêche JavaScript de lire le cookie, sans pour autant bloquer toutes les actions que du code malveillant peut effectuer dans une session active.

Par où commencer pour vérifier son propre site ?

Suivez le parcours des données d’un champ, depuis leur réception jusqu’à chacun des endroits où elles sont affichées. Un commentaire peut être affiché sans risque sous un article, mais devenir dangereux dans le panneau de modération ou dans l’aperçu d’une notification. Vérifiez également les utilisations de innerHTML et des fonctions permettant de contourner l’encodage automatique.

L’étape suivante consiste à tester dans un environnement isolé : déterminez si le contenu saisi s’affiche comme du texte ou s’il modifie la structure de la page. Après la correction, ajoutez un test de non-régression qui détectera si ces données sont à nouveau traitées comme du HTML.

À lire aussi : Qu’est-ce que la 2FA ?

À lire aussi

Découvrez comment PHP-FPM traite les requêtes PHP, son rôle face au serveur web et comment adapter ses processus au trafic.
Découvrez BIND, logiciel libre de serveur DNS : ses rôles, la gestion des domaines et les cas où le déployer vous-même.
Découvrez le registre polonais REGON, son numéro, ses différences avec NIP et KRS et comment vérifier les données d’une entreprise.