PHP-Nuke : Cross Site Scripting Permanent
*****************************************
Informations :
°°°°°°°°°°°°°°
Langage : PHP
Website : http://www.phpnuke.org
Version testée : 6.5 FINAL
Problème : Cross Site Scripting
Developpement :
°°°°°°°°°°°°°°°
Plus besoin de présenter PHP-Nuke...
J'ai aussi testé ce qui suit sur la version 6.5.1 FR de phpnuke-france (http://www.phpnuke-france.org) avec succès.
Francisco Burzi a été prévenu le 11 avril, ainsi que le webmaster de phpnuke-france, le 12.
A la base, ce texte avait pour but de parler uniquement des problèmes de XSS (Cross Site Scripting) dans PHP-Nuke via
les feuilles de style et les balises <style>, mais tant que j'y étais à farfouiller dans les possibilités de failles
du HTML, j'ai un peu elargit le sujet.
Rapellons qu'un XSS permanent est un ligne de code html/javascriot/vbscript/... qui reste à un endroit définit du site,
qui n'est donc pas simplement injecté via une url mais enregistré dans le site lui-même.
On va donc pouvoir injecter du javascript grâce aux balises html.
J'ai pu en injecter dans :
- le profil
- les messages privés (pas avec le module phpBB)
- les commentaires
Un javascript pourrait facilement récuperer le cookie de l'utilisateur permettant de l'authentifier.
Commençons par le problème du profile, qui est legerement different des autres, dans sa façon d'injecter le code.
Dans le profil, deux informations peuvent être affichées sous forme d'hyperliens : l'e-mail et le site web de l'utilisateur.
Ces deux éléments seront donc affichés dans le code html du profil dans une balise <a>.
Par exemple l'email (qui ne sera affiché que si l'utilisateur le désire) :
<a href="mailto:em@i.l">em@i.l</a>
et le site :
<a href="http://www.website.com">http://www.website.com</a>
Des filtres dans phpnuke empêchent l'insertion de caractères < ou > dans le profile.
Mais nulle part dans le site le caractères " est filtré.
Par conséquent, si on entre dans le profile comme site web par exemple : http://www.site.com"aaaa, le site web enregistré
dans la base de données sera bien http://www.site.com"aaaa, mais celui sur lequel on cliquera dans l'affichage du profile
sera http://www.site.com.
En effet, le code html des liens est du style :
<a href="LESITE">LESITE</a>
Dans ce cas-ci, ça donnera donc :
<a href="http://www.site.com"aaaa">http://www.site.com"aaaa</a>
On pourra alors ajouter des éléments à la balise qui, en fonction des actions executées par l'utilisateur, pourront faire
executer un javascript.
Par exemple onClick, qui s'execute si on clique sur le lien !
Si on entre comme site web sur le profile :
http://" onclick="alert('test')
sur le profile le code sera :
<a href="http://" onclick="alert('test')">http://" onclick="alert('test')</a>
Si quelqu'un clique dessus, il verra s'afficher une messagebox avec 'test' dedans.
On aurait pu utiliser onDblClick, onHelp, onMouseDown, onMouseMove, onMouseOut, onMouseOver, onMouseUp,...
Mais ce système a deux inconvenients majeurs.
D'abord il faut que l'utilisateur fasse quelque chose de spécial pour que le script soit executé.
Ensuite le script executé est visible par tous, puisque l'url du site est affichée.
C'est la qu'intervient les feuilles de styles, que nous pouvons utiliser pour régler ces deux problèmes.
On peut cacher l'url grâce à style="visibility:hidden;".
Si on entre comme site http://" onclick="alert('test')" style="visibility:hidden;, ça donnera le code html :
<a href="http://" onclick="alert('test')" style="visibility:hidden;">http://" onclick="alert('test')" style="visibility:hidden;</a>
Voilà donc un problème réglé, mais du coup, comme le lien n'est pas visible, l'utilisateur ne saurait pas sur quoi cliquer.
Le mieux est donc de trouver un moyen de faire executer du javascript de puis le style... ce qui est tout à fait possible,
grâce à deux fonctions.
Ce sont url() et expression(). La première, url(), ne fonctionne pas avec NE4. Elle envois une requête à une url.
expression() execute directement le code donné en argument. Je crois que cette dernière fonction ne fonctionne
qu'à partir de IE5.5.
Il y a donc plus de chance que la fonction url() fonctionne chez la victime.
Voyons comment s'utilisent ces fonctions.
Il y a de nombreux arguments possibles dans les feuilles de style : top:, background:, visibility:, left:, overflow:,
border:, font:,...
Un point fort pour la fonction expression() est qu'elle peut s'utiliser dans TOUT les arguments de style.
url(), elle, ne peut s'utiliser que dans certains arguments, dont j'ai essayé de faire la liste :
- background:
- background-image:
- list-style:
- list-style-image:
- cursor:
- behavior:
J'ai aussi entendu parler de binding: dans http://www.idefense.com/idpapers/XSS.pdf, mais je n'ai pas réussi à le faire
fonctionner, ainsi que, dans les dernières versions de css, dans @media, @import et @font-face, mais je pense que c'est
uniquement utilisable directement dans les balises <style></style>.
Comme je ne suis jamais sûr que la documentation trouvée à ce sujet était complète, si quelqu'un à des précisions,
merci de m'en faire profiter :)
Voici trois schèma de possibilité pour faire executer un javascript ("alert()" dans ce cas), via le style :
<balise style="background:url(javascript:alert());"></balise>
<balise style="background:url('javascript:alert()');"></balise>
<balise style="[argument]:expression(alert());"></balise>
url() execute une fois l'url (donc le javascript), par contre expression() est une chaîne sans fin, qui executera le
javascript jusqu'à ce que la page soit quittée.
Donc, pour faire executer une fois la fonction javascript alert() sur le profile, via l'url du site web, sans que le
script soit visible, il faudra entrer comme site par exemple :
http://" style="list-style:url(javascript:alert()); visibility:hidden;
et pour le faire executer à l'infini par exemple :
http://" style="zoom:expression(alert()); visibility:hidden;
La même chose est possible via l'e-mail.
Voilà pour le profile :)
Comme j'ai dit le reste est le même principe.
Au moins dans les commentaires et les messages privés (sauf quand c'est le module phpBB), certaines balises html
sont autorisées.
En voici la liste "officielle" qui est bien suffisante pour mettre en cause la sûreté des comptes :
- <b>
- <i>
- <a>
- <em>
- <br>
- <strong>
- <blockquote>
- <tt>
- <li>
- <ol>
- <ul>
On retouve notre balise <a>, et bien d'autres pour lesquelles l'utilisation du style est similaire.
En effet, <balise style="background:url(javascript:alert());"></balise> peut être
<a style="background:url(javascript:alert());"></a> comme dans le profile, de la même façon que
<b style="background:url(javascript:alert());"></b> ou <br style="background:url(javascript:alert());"> ou
<blockquote style="background:url(javascript:alert());"></blockquote> etc...
On aurait pu encore une fois utiliser onclick="" etc mais comme on a vu c'est pas le plus pratique.
Donc si je met dans un commentaire, par exemple :
<br style="overflow:expression(alert());">, le javascript sera correctement executé chez tout ceux qui visualiseront le
commentaire.
Par contre il me sera impossible d'envoyer dans un commentaire le
<blockquote style="background:url(javascript:alert());"></blockquote> dont j'ai parlé plus haut.
En effet, PHP-Nuke contient un filtre empechant l'envois du mot "script" si il est entre les caractères < et >, ce qui
est le cas ici.
Pour passer ce filtre, il suffit par exemple de remplacer la lettre c de script par sa valeur cryptée c, pour donner
quelque chose du style :
<b style="list-style-image:url('javascript:alert()');"></b>
Patch :
°°°°°°°
Un patch est disponible sur http://www.phpsecure.info.
Il remplace les mots :
'url(','expression(','onclick','ondblclick','onhelp','onmousedown','onmousemove','onmouseout','onmouseover','onmouseup','onblur','onafterupdate','onbeforeupdate','onkeydown','onkeypress','onkeyup','onfocus','onerror','onload','onunload'
par :
'url*(','noexpression(','on*click','on*dblclick','on*help','on*mousedown','on*mousemove','on*mouseout','on*mouseover','on*mouseup','on*blur','on*afterupdate','on*beforeupdate','on*keydown','on*keypress','on*keyup','on*focus','on*error','on*load','on*unload'
les rendant inutilisables. C'est le système qu'utilisent hotmail, caramail,...
Ce n'est pas le plus sûr, mais le moins restrictifs.
Greetz :
°°°°°°°°
http://www.yoyodesign.org pour ses textes sur les feuilles de style.
Le programme TopStyle Lite qui m'a permis de faire des tests sur ces dernières.
http://olivier.bichler.free.fr sur ses précisions au niveau des balises html.
Credits :
°°°°°°°°°
Auteur : frog-m@n
E-mail : leseulfrog@hotmail.com
Websites : http://www.phpsecure.info, http://www.frog-man.org
Date : 24/04/03
Copyright frog-m@n
http://www.phpsecure.info/v2/zone/pArticle