Détecter et exploiter une XSS

To the non-french speaker, note that you can translate the articles using the Google Trad widget situated at the bottom of all pages.


La faille XSS (Cross Site Scripting) est une faille web permettant d’utiliser du code javascript et HTML dans des champs non protégés. Par exemple dans un formulaire. A l’origine on l’appelait la faille CSS mais pour ne pas la confondre avec le CSS du Cascade Style Sheet elle a été renommée.

Le premier fichier est un simple formulaire HTML qui envoie des données via la méthode GET (donc dans l’URL). Puis le programme affiche la donnée envoyée.

form.png

Et du coup ça ressemble à ça :

form.png

Comme je vous l’ai dit la faille XSS permet d’entrer du code HTML et javascript dans des champs non sécurisés. On va donc s’amuser à entrer du code HTML dans notre formulaire. On peut par exemple demander à ce que notre pseudo soit écrit en très gros à l’aide de la balise h1:

h1.png

Bon tout ça c’est bien marrant mais actuellement on peut rien faire de bien dangereux avec. Par contre avec du javascript on peut aller beaucoup plus loin !

Un élément extrêmement utilisé en javascript est « l’alert », sur mon ancien site lorsque vous entrez dans la section sécurité vous avez une sorte de pop-up qui apparaît. Cela est fait à l’aide d’une alert javascript.
Voici la syntaxe d’une alert javascript :

"alert("Votre texte")"

Insérons ceci dans notre formulaire et voilà ce que l’on obtient :

alerte

Avant de continuer je vais vous expliquer rapidement ce qu’est un cookie. Un cookie, c’est un petit fichier texte stocké dans votre navigateur. Lorsque vous vous connectez à votre boite mail, on vous demande si vous souhaitez « enregistrez votre identifiant et votre mot de passe » ou encore « voulez-vous que l’on se souvienne de vous » etc…

Si vous acceptez alors le navigateur va créer un cookie contenant votre identifiant ainsi que votre mot de passe (ou plus généralement un cookie de session). Ainsi, lorsque vous vous reconnecterez à votre boite mail, vous n’aurez même plus besoin d’entrer votre id et mdp dans le formulaire d’identification puisque le navigateur l’aura déjà fait à votre place.

Reprenons le code de notre fichier PHP, je vais y ajouter deux variables de type cookie appelées « identifiant » et « motdepasse » En premier argument nous avons le nom du cookie, en second sa valeur et enfin le temps avant que le cookie ne s’autodétruise.

Voici donc le nouveau code de notre fichier PHP :

cookie+


En JavaScript il existe une syntaxe qui permet de récupérer les cookies de notre navigateur, cette syntaxe est la suivante :

"alert(document.cookie)"

Essayons là en live :

cookie++.png

Oops … Bah voilà je me suis volé mes propres cookies d’authentification et je vais pouvoir me connecter à ma boite mail. Vous me direz que de toute façon ce n’est pas si grave cette faille, personne ne pourra s’en servir contre vous puisque les cookies sont stockés sur votre ordinateur !
A ça je répondrai que vous avez à moitié raison. En effet nous venons de voir un type de faille XSS, le XSS dit réfléchi AKA non-permanent. Il en existe un deuxième type beaucoup plus dangereux.


Ce deuxième type de XSS est le XSS stocké AKA permanent. Dans ce cas de XSS le code exécuté dans le formulaire est stocké dans une base de données et peut-être exécuté par des personnes lambda qui viennent de partout sur Terre. Typiquement on retrouve ce genre de failles dans les livres d’or de sites web, dans les zones de commentaires et même dans des images… Bref tous les endroits où l’utilisateur peut laissez quelque chose de sa création.

Encore pire, si je vous disais qu’en cliquant sur un lien, je pouvais récupérer tous vos cookies ? Effrayant non ? Je vais vous montrer comment tout cela fonctionne.

Prenons le cas d’un livre d’or. C’est une page web sur laquelle des utilisateurs peuvent laisser des messages par exemple pour noter un musée, un hôtel ou autre. Tous les messages sont stockés dans une base de données.

Dans cet exemple je vais avoir besoin d’une base de données qui stocke les utilisateurs ainsi que les commentaires laissés par ces mêmes utilisateurs.

bdd

Dans la table utilisateur, nous insérons deux utilisateurs : l’administrateur du site et un utilisateur lambda.

insertion

Comme vous pouvez le voir, l’utilisateur 1 est l’administrateur du site. L’utilisateur 2 est une personne lambda qui vient poster un message. Enfin pas si lambda puisqu’on va voler les identifiants de l’administrateur !

Supposons que l’utilisateur se connecte sur le site :

co1

Il arrive sur la page du livre d’or :

resco1

Il n’y a pas encore de message ! Bon bah on va en ajouter un (inoffensif cette fois).

mes1

Et le résultat :

resmes1

Mon message est bien là !
Maintenant la question qu’il faut se poser est : « est-ce que les champs sont protégés contre le XSS » ?
On va voir ça tout de suite :

xssn1

Et le résultat :

xssrn1

Notre message apparaît bien en gras et en italique. XSS est donc utilisable.

Essayons d’entrer une alert JavaScript à la place du texte :

testxssr1

Et du coup si on se reconnecte sur le site voici ce que l’on voit :

testxss1res

A ce moment-là, on peut dire que l’administrateur du site va avoir de sérieux problème ahah !!
Bon on va aller plus loin et cette fois-ci on va laisser comme message ce bout de code que vous avez déjà vu plus tôt :

idmdp

Sans surprise on récupère les cookies de l’utilisateur. Si l’administrateur se connecte, il verra ses propres cookies s’afficher (donc son identifiant et son mot de passe). Maintenant que nous avons infecté la base de données avec notre message piégé il serait intéressant de pouvoir récupérer le contenu de l’alerte.

Oui mais comment faire ? Les cookies sont toujours stockés sur le pc de l’administrateur ! Eh bien on va tout simplement créer une alert qui redirigera l’administrateur vers une page web pirate (la nôtre) qui récupérera les cookies des personnes qui s’y connectent !
Eh oui ! En javascript on peut rediriger les utilisateurs avec une ligne de code :

"window.location("http://monsite.fr");

Si j’entre ce code dans le formulaire, alors toutes les personnes qui iront sur la page du livre d’or du site seront redirigées vers le site google.fr. Par conséquent si j’ai le bon code javascript, le bon script PHP et un administrateur peu soucieux de la sécurité je vais facilement pouvoir récupérer des cookies qui ne sont pas les miens.

Voici le script PHP que l’on va utiliser :

code.png

Et le message que nous allons déposer sur le livre d’or :

redirection

EDIT : Oui, il manque la ligne qui permet d’effectuer la redirection sur l’image, my bad..

Voilà le résultat :

resultat

Maintenant si on se logue en tant qu’administrateur et qu’on ouvre la page livre d’or et bien le pirate aura accès aux cookies de l’administrateur !

Voici le contenu du fichier texte après la connexion de l’administrateur :

blocnote

A partir de maintenant toute personne qui se connectera sur la page « Livre d’or » donnera involontairement au hacker l’ensemble de ces cookies. Ce n’est bien évidement pas la seule manière de récupérer les cookies. Il suffit d’être imaginatif pour en trouver pleins d’autres !

EDIT : une version améliorée du script est disponible ici.


Se protéger de la faille XSS

Sans surprise la meilleure façon de se protéger des failles XSS est d’utiliser les fonctions d’échappement des caractères spéciaux ainsi que des filtres. Aussi, si vous voulez sécuriser votre site vous avez tout intérêt à empiler les fonctions de filtrage les unes avec les autres :

protectionxss

La première ligne du code permet de réceptionner l’input de l’utilisateur. Ensuite j’ai déclaré un tableau qui contient une liste –non exhaustive– de mots que je considère comme étant illégaux. J’aurais pu rajouter pas mal d’autres mots comme par exemple la fonction eval() en Javascript qui est un vecteur potentiel de XSS. Pareil pour les méthodes onload, onclick, on mouseover etc…

La troisième ligne contient tous les filtres que j’ai empilé les uns sur les autres. Les fonctions filter_var() et htmlspecialchars() suppriment ou remplacent tous les caractères indésirables : < > ‘ « . Quant à la fonction str_replace, elle remplace tous les mots de l’input contenues dans le tableau $illegal par youwontgetmekiddo.

Résultat, si j’envoie ça :

test.png

Je reçois ça :

fail

Pour finir il peut être intéressant de filtrer les inputs via une Regex. En effet si l’input est un champ de recherche alors on ne devrait pas avoir besoin d’utiliser les caractères « <« . On pourrait donc filtrer l’input avec une regex alphanumérique 🙂 !

EDIT 2018 : Comme @Anass l’a fait remarquer. Il est toujours possible de bypass ces fonctions de protection. Par conséquent j’écrirai un second article sur la faille XSS d’ici quelques semaines.


Voilà ! Cet article sur la faille XSS est terminé. Comme vous avez pu le constater, cette faille est beaucoup plus violente que ce que l’on aurait pu imaginer. Il faut donc impérativement s’en protéger.

2 commentaires

Laisser un commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l'aide de votre compte WordPress.com. Déconnexion /  Changer )

Photo Google

Vous commentez à l'aide de votre compte Google. Déconnexion /  Changer )

Image Twitter

Vous commentez à l'aide de votre compte Twitter. Déconnexion /  Changer )

Photo Facebook

Vous commentez à l'aide de votre compte Facebook. Déconnexion /  Changer )

Connexion à %s