Il s'agissait donc de tester un service sur maquette. Un service fourni par un leader du marché en terme de sécurité paraît-il. Et en particulier l'équipement avec lequel interagit l'utilisateur du service. Interaction qui se fait bien évidemment à travers un portail web. L'état des lieux est rapide : c'est du Linux, un serveur Apache, des pages en PHP, pas d'autre service accessible. Rien de bien original. Je ne pense pas tuer le suspense en vous annonçant d'emblée un dénouement somme toute assez attendue : la machine va se faire rooter à la fin. Ou plutôt au milieu...

Les ingrédients ? Les classiques. D'abord, un script d'include qui fait lui-même une inclusion d'un fichier dont le nom est dérivé de la valeur d'un paramètre passé en argument. Ensuite, des register_globals et allow_url_fopen activés. N'en jetez plus, l'affaire est jugée. Emballez, c'est pesé. Vous avez un joli directory traversal agrémenté d'une magnifique exécution de code arbitraire à distance sur la machine. Sans même parler de la version de PHP vulnérable à je ne sais combien de failles locales, vous avez là les ingédients d'un shell distant. Le truc rigolo, c'est qu'avant d'en arriver là, Nico avait sorti un CGI de la machine. Huit malheureux kilo-octets et quelques dix fonctions. Cinq dépassements de tampon. Le mec qui a codé ça devrait apprendre à coder un peu. Sauf qu'après une analyse que j'ai du mal à qualifier autrement que d'acharnée, aucun ne s'avèrera exploitable. Ce mec devrait donc également penser à jouer au loto...

Le problème, c'est que ni Nico ni moi ne sommes des brutes en PHP, contrairement à d'autres. Mais les maigres connaissances qui me suffisent à gérer ce blog me permettront d'adapter rapidement une petite backdoor en PHP au contexte et uploader le lot d'outils classiques, netcat en tête, bien évidemment. Puis noter au passage que si les fonctions dangereuses ne sont pas désactivées, les protections à deux balles, elles, le sont. Ainsi, le magic_quotes_gpc est bel et bien là... C'est ce qui doit expliquer que l'auteur ait ressenti le besoin de recourir à la fonction stripslashes à chaque fois qu'il devait traiter une chaînes de caractères...

Mais tout n'est pas si noir. Le process Apache est chrooté ! Sauf qu'il se trouve que l'application web devant interagir avec des processus tournant à l'extérieur de la chroot, il dispose pour se faire d'un truc que j'ai du mal à comparer à autre chose qu'un simple pipe avec un process root de l'autre côté. Ce dernier, qui doit probablement traîner son lot de vulnérabilité est chargé de lire des paramètres et de les passer à des scripts shell... Point-virgule mon amour, injection de commandes, etc. Rien ne nous est épargné.

En résumé, un vrai carnage.


Pourquoi donc de la nostalgie ? Ce genre d'expérience est vécue régulièrement par tous ceux qui pratiquent régulièrement l'art du test d'intrusion. Nostalgie donc parce que ça me rappelle étrangement un de mes tous premiers pentests, du temps où je sévissais encore chez Cartel Sécurité. Autant dire que ça fait un bail. Un peu plus de cinq ans en fait puisque c'était en 2002. Un test dont le point de départ avait été... Un hébergement web mal configuré, avec un upload mal maîtrisé d'un côté conjugué à un magnifique directory traversal de l'autre, qu'on aurait aussi pu transformer en exécution de code avec une inclusion distante en fait. Bref, quelque chose de très similaire.

Voilà, cinq ans se sont écoulés. Cinq ans que certains ont passé à produire des HOWTO, des présentations, des livres, des tutoriels, je ne sais quelle quantité impressionnante de documentation sur la programmation web, et on trouve encore et toujours les mêmes problèmes. Je ne devrais pas m'en étonner. Et je ne m'en étonne d'ailleurs pas. Ça me navre. C'est tout.

Ça me navre d'autant plus que j'arrive à m'expliquer la configuration un peu laxiste de certains hébergements ou l'utilisation légère de certaines fonctions dans des applications Web grand public juste pour que ça marche. Encore qu'on notera ici un certain cercle vicieux qu'il faudrait penser à casser un jour. Mais dans ce dernier pentest, il s'agit d'une appliance. Les personnes qui développent ça maîtrisent tout de A à Z. Ils ne sont pas face à une application tordue[1]. Ils ne sont pas face à un serveur web à la configuration figée. Non, ils peuvent tout configurer comme bon leur semble. Et c'est ça qui me navre.

Parce que quand on maîtrise tout, il est simple d'avoir des register_globals et allow_url_fopen désactivé. Ce n'est pas grand chose, mais vous allez ainsi rendre inexploitables la plupart des failles annoncées comme exécution distante de code arbitraire sur application PHP. Exemple, la faille sur Dotclear 1.2.4 qui permettait d'inclure du code arbitraire passe à la trappe. Mais aussi du code qu'on voudrait voir marche, comme ce plugin Wikio pour Dotclear qui nous fait un très apprécié :

$wn = file("http://".$wikioUrl."/getnote?u=".MD5($wikioThisUrl)
        ."&i=".$wikioCliIp."&referer=".MD5($wikioReferer));

Ou tout autre code n'utilisant pas de bibliothèque plus adaptée pour aller consulter une URL. Et à bien y réfléchir, on n'a pas envie de voir marcher ce genre de code...

Autre truc quand on code soi-même l'application, ou qu'on n'a pas la flemme de la patcher violemment : sortir les includes de la racine de publication web. Et n'y laisser que les scripts et objets qui doivent être appelés en URL. Et bien oui, contrairement à une légende urbaine qui a la vie dure, PHP peut aller lire des fichiers en dehors de la webroot. Si c'est souvent un problème en cas de directory traversal, c'est quelque chose qui permet de rendre nombre de fichiers inaccessibles via une simple URL. Impact ? La faille précédemment évoquée n'est pas exploitable, puisqu'elle demande l'accès direct à un script inclus.

J'avoue. J'ai eu le flemme de le faire pour Dotclear, mais je ne pense pas que ce serait vraiment difficile. J'en ai presque honte d'ailleurs. Mais là n'est pas la question. Je ne suis qu'un amateur en PHP, qui lit de temps à autre la référence en ligne pour modifier deux ou trois lignes de code. Sans plus. Mais même ça, je le sais. Et pourtant, je ne vends pas mon blog au tout venant comme un site super sécurisé[2].

Ces maigres "conseils" ne rendront clairement pas votre application invulnérable[3], loin s'en faut, mais c'est déjà un grand pas dans la bonne direction.


Voilà, voilà, voilà. C'était le passage nostalgie de 2007 et plus. Nostalgie d'autant plus marquée que j'ai l'impression qu'il s'agira très certainement d'un de mes tous derniers pentests. Snif...

Sur ce, je vous laisse à votre réveillon, et, pendant que je me prépare à rejoindre mes amis pour faire enterrer dignement l'année 2007, vous souhaite de tout cœur une très bonne année 2008, ainsi que tout ce qui va avec.

Notes

[1] Enfin, pas vraiment, mais vous voyez ce que je veux dire.

[2] Même si me ferait mal de me faire pwned...

[3] Comme si ça existait, les applications invulnérables...