Cross-Site Scripting (XSS)

1. PrincipeMain en arriere fleche dessinee 318 51824

L'OWASP considère la vulnérabilité à XSS comme une faille critique car elle est très répandue et facile à détecter. Les attaques s'appuient principalement sur les formulaires des applications Web. Les victimes sont les utilisateurs des applications Web vulnérables. L'ANSSI signale dans la note d'information CERTA-2002-INF-001-001 que les scripts frauduleux peuvent endommager la base de registre de la victime, afficher des formulaires dont les saisies seront envoyées à l'attaquant, récupérer les cookies présents sur la machine de la victime, exécuter des commandes systèmes et construire des liens déguisés vers des sites malveillants.

Y.-W. Huang, C.-H. Tsai, T.-P. Lin, S.-K. H., D.T. Lee et S.-Y. Kuo [10] indiquent que l'attaque XSS est également une attaque par injection car l'objectif de l'attaquant est de soumettre un code frauduleux à l'application. A. Kiezun, P. J. Guo, K. Jayaraman, M. D. Ernst [11] montrent qu'il existe en fait deux types d'attaque XSS.

L'attaque XSS par réflexion (reflected XSS) s'appuie sur le fait que l'application Web affiche ce que l'utilisateur vient de saisir dans un formulaire dans une page de résultat. Le navigateur de la victime exécute alors le code frauduleux généré dans la page de résultat. Tous les champs de formulaire sont donc une faille de sécurité potentielle que l'attaquant peut exploiter par XSS. L'attaquant crée un lien déguisé vers l'application Web dont un des paramètres contient du code JavaScript frauduleux. En utilisant ce lien, la victime fait exécuter par son navigateur le code JavaScript. Le Web 2.0 et ses systèmes de gestion de contenu ont popularisé cette attaque en permettant de publier des liens aisément et visibles sur tout le Web.

Image non disponible
Figure 12 - Principe d'une attaque XSS par réflexion

L'attaque XSS stockée (stored XSS) s'appuie sur le fait que l'attaquant réussisse à stocker dans la base de données du code frauduleux qui sera exécuté par la victime lorsqu'elle tentera d'afficher la donnée malveillante. Cette attaque est plus dangereuse que la première car le code fait partie intégrante des données de l'application Web et peut atteindre plusieurs victimes.

Image non disponible
Figure 13 - Principe d'une attaque XSS stockée

2. Exemples d'attaque

L'attaque XSS par réflexion peut être implémentée par différents moyens.

Le plus facile est d'utiliser un moteur de recherche vulnérable. Par exemple les outils de forum intègrent des formulaires pour recherche des messages par leur contenu. La page de résultat reprend généralement les mots-clés saisis. Il suffit alors de mettre comme paramètre de recherche un code JavaScript qui sera ensuite interprété par le navigateur de la victime. Pour réaliser cette attaque, il suffit de laisser un lien qui aura pour paramètre le code malveillant.

Figure 14 - Exemple de lien malveillant exploitant une faille XSS

Sélectionnez

http://www.forum-vulnérable.com/recherche.php?parametre=<script>alert(&#8216;attaque XSS')</script>

En cliquant sur ce lien, la victime lancera la recherche. Puis le moteur de recherche affichera le paramètre « <script>alert(‘attaque XSS')</script> » qui sera exécuté par le navigateur.

Des applications Web sont responsables de l'affichage des courriers électroniques : les webmails. Pour consulter son courrier, l'utilisateur va préalablement s'authentifier et ses informations d'identification seront stockées dans des cookies. Un courrier malveillant peut intégrer du code JavaScript qui sera interprété par le navigateur. Ce code sera capable de récupérer les cookies et envoyer les informations à l'attaquant.

L'attaque XSS stockée injecte du code malveillant dans la base de données. L'application Web suivante de type forum va permettre d'illustrer cette attaque. La table support de la démonstration est la suivante :

Figure 15 - Script SQL de création de la table « messages »

Sélectionnez

CREATE TABLE IF NOT EXISTS `messages` ( 
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'identifiant', 
`numerosujet` int(11) NOT NULL COMMENT 'numero du sujet', 
`redacteur` varchar(30) NOT NULL COMMENT 'nom du redacteur du message', `message` varchar(4000) NOT NULL COMMENT 'contenu du message', 
PRIMARY KEY (`id`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=6 ;

Le script PHP suivant est responsable de l'enregistrement d'un message. Comme une des informations saisies (le nom du rédacteur) est réaffichée, cela implique que ce code est vulnérable à une attaque XSS par réflexion.

Figure 16 - Script PHP pour l'insertion dans la table « messages »

Sélectionnez

<?php 
//recuperation des parametres 
$message=$_GET['message']; 
$nom=$_GET['nom']; 
$numsujet=$_GET['numsujet']; 
//generation de la requete 
$requeteSQL = "INSERT INTO messages VALUES (NULL, '$numsujet', '$nom', '$message')"; 
//execution de la requete 
$reponse = mysql_query($requeteSQL); 
//affichage du resultat 
echo "<tr><td>&nbsp;</td><td>Merci $nom de votre participation. Vous venez de saisir : $message</td></tr>"; 
?>

En saisissant comme message un code JavaScript malveillant, il sera enregistré dans la base de données.

Le script PHP suivant est responsable de l'affichage de l'ensemble des messages d'un sujet.

Figure 17 - Script PHP pour la recherche dans la table « messages »

Sélectionnez

<?php 
//recuperation des parametres 
$numsujet=$_GET['searchsujet']; 
//generation de la requete 
$requeteSQL = "SELECT * FROM messages WHERE numerosujet=$numsujet order by id"; 
//execution de la requete 
$reponse = mysql_query($requeteSQL); 
//affichage du resultat 
echo "<tr><td> Sujet $numsujet</td><td>"; 
while($resultat = mysql_fetch_assoc($reponse)) { 
    echo $resultat['redacteur'] . " : " . $resultat['message'] . "<br>"; 
} 
echo "</td></tr>"; 
?>

Lorsque des utilisateurs afficheront le fil des messages, le message frauduleux sera automatiquement envoyé aux navigateurs et interprété créant une attaque XSS.

3. Parade et bonnes pratiques

Les recommandations faites précédemment pour se prémunir des risques d'injection sont valables pour XSS. Cependant, transformer les six caractères douteux suivants suffit.

Figure 18 - Caractères spéciaux à remplacer par leur code

Sélectionnez

& &#61664; &amp; 
< &#61664; &lt; 
> &#61664; &gt; 
" &#61664; &quot; 
' &#61664; &#x27; (&apos; n'est pas recommandé) 
/ &#61664; &#x2F;

Côté client avec JavaScript il faut vérifier les données saisies par les utilisateurs. Côté serveur, il faut vérifier les données récupérées en paramètre. Il faut rejeter toutes les données qui ne sont pas conformes à ce qui est attendu.

Pour éviter le vol de cookies par du code JavaScript, il est possible de positionner l'attribut de cookie HTTPOnly [8]. S'il est présent, le navigateur interdit au moteur JavaScript de lire ou écrire dans les cookies. Cet attribut est très peu utilisé par les applications Web, car tous les navigateurs ne le gèrent pas. Cependant il est préférable de l'utiliser car les navigateurs les plus populaires l'implémentent, ce qui diminue les risques liés aux cookies.

Figure 19 - Script PHP pour positionner l'attribut de cookie HTTPOnly

Sélectionnez

<?php 
session.cookie_httponly = True 
?>

Les navigateurs intègrent des protections contre XSS en interdisant l'exécution de code JavaScript qui modifie une page Web depuis une page Web ne portant pas le même nom de domaine.