Apprendre PHP & MySQL : Faille de Sécurité XSS

La faille « cross-site scripting » (abrégée XSS) est une incontournable faille de sécurité web qu'il est important de comprendre afin de s'en prémunir.

Icône de calendrier
Intermédiaire
12 chapitres

Qu’est-ce qu’une faille XSS ?

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 dans les navigateurs web des visiteurs de la page.

Pour injecter ce code malveillant, les attaquants exploitent les entrées utilisateurs que sont les formulaires, ainsi que l’URL d’une page (via la chaîne de requête).

Pour plus d’informations, je vous invite à consulter le guide dédié aux failles XSS.

Comment se protéger des failles XSS en PHP ?

Pour prémunir toute faille XSS, la règle d’or consiste à échapper les caractères spéciaux des saisies utilisateurs.

Considérons la saisie utilisateur <script>alert('Oups, faille XSS !');</script> dans le champ title de publication d’un article de blog.

Du code JS sera donc enregistré en base de données, au sein de la table articles :

idtitlepublished_atauthor_id
1<script>alert('Oups, faille XSS !');</script>2024-05-14 12:46:3712

Les problèmes arrivent lorsqu’il s’agit d’afficher le titre de cet article sur une page.

❌ Danger des caractères spéciaux

Si les caractères spéciaux (>, ', <…) ne sont pas échappés, alors le navigateur les interprétera tels quels et le script sera interpreté.

Admettons que le titre de notre article soit contenu dans la propriété title d’un objet $article :

mapage.php
copié !
	<article>
		<h1><?= $article->getTitle() ?></h1>
		...
	</article>

⚠️ Ici $article->getTitle() vaut <script>alert('Oups, faille XSS !');</script>

✅ Echapper les caractères spéciaux avec htmlspecialchars()

La solution consiste alors à échapper les caractères spéciaux des textes envoyés par l’utilisateur, et qui sont susceptibles d’être affichés sur une page web.

En PHP, c’est du côté de la fonction htmlspecialchars() que l’on se tournera. Son 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;

Le titre de notre article sera alors affiché sans le moindre risque.

mapage.php
copié !
	<article>
		<h1><?= htmlspecialchars($article->getTitle()) ?></h1>
		...
	</article>

✅ Ici htmlspecialchars($article->getTitle()) vaut &lt;script&gt;alert(&#039;Oups, faille XSS !&#039;);&lt;/script&gt;

La fonction htmlspecialchars() est à utiliser en sortie uniquement, c'est-à-dire lors de l'affichage.

La fonction htmlspecialchars() doit uniquement être utilisée au moment de l’affichage, pas lors de l’enregistrement en base de données pour plusieurs raisons :

  1. Séparation des préoccupations : La base de données doit stocker les données brutes. Toute transformation, comme l’encodage HTML, doit être effectuée lors de la sortie des données pour une flexibilité maximale.
  2. Préservation des données originales : En enregistrant les données brutes, il est possible de les réutiliser dans différents contextes (HTML, JSON, API, etc.), sans avoir à les décoder.
  3. Meilleure gestion des encodages : Chaque contexte de sortie (HTML, XML, JavaScript) peut nécessiter un encodage différent.

Vous conviendrez qu’une petite alert() JS n’est pas bien méchante mais, comme détaillée dans ce guide dédié aux failles XSS, le JavaScript nous offre des possibilités bien plus sombres !