« Virus » et piratage WordPress : histoire d’une infestation et de leur éradication

Ces dernières années, WordPress a comporté – il faut le reconnaître – de nombreuses failles (ou bien dans ses plugins et autres thèmes) permettant à des opportunistes malfaisants  de prendre le contrôle de serveurs utilisant WordPress, victime de son succès.

Je protégeais simplement mon site par des mots de passe complexes, des mises à jour WordPress régulières, et une stratégie simple consistant à mettre le moins de plugins possible. Très récemment, j’ai été victime de nombreuses infestations, que l’on peut comparer – pour faire simple – à des virus informatiques. Ils ont des stratégies assez similaires : prendre le contrôle de façon relativement discrète, laisser fonctionner normalement le WordPress (afin que le responsable ne s’en rende pas compte) puis déclencher le fonctionnement de l’exploitation du site au moment opportun, et massivement.

Un WordPress disposant de la capacité d’envoyer des emails, il devient par ailleurs une cible de choix., et permet ainsi la génération de mails de spam en masse, le temps que vous soyez blacklistés!

Ayant été averti simultanément par mon hébergeur et par Google, j’ai pu identifier, bloquer, et effacer assez rapidement les processus déclenchés par les « virus » en deux ou trois jours. Depuis, je les vois essayer encore de prendre le contrôle, mais les protections mises en place les empêchent de procéder.

Vous me direz « pourquoi n’as-tu-pas mis tous les plugins de sécurité ? ». Certes…

Je suis relativement peu enclin à utiliser ces « plugin de sécurité », souvent payants, alourdissant parfois considérablement le fonctionnement naturel de votre WordPress, et ne garantissant pas finalement à 100% l’étanchéité de votre site Web. Par ailleurs ces plugins existent par dizaines, sont tous relativement bien notés : lequel choisir ? Les mettre tous sans savoir ce qui est fait précisément ? Ceux que j’ai pu voir vous avertissent juste « il y a un problème », mais ne vous disent pas d’où vient le problème, ni comment enlever le virus.

Vous pouvez bien sûr procéder avec ces plugins si vous en êtes content. Mettez en commentaire les références du plugins s’il a fait ses preuves pour vous.

Mais voilà, je suis vieux jeu, et je voulais comprendre ce qui était arrivé, et comment l’éviter.

Je tiens à préciser que je ne suis pas un spécialiste de la sécurité WordPress. Les « virus » (pour faire simples) que j’ai pu découvrir correspondent à des technologies de maintenant. Ils y en a certainement d’autres et il y en aura d’autres.

Bref, si vous maîtrisez un peu les commandes système et que vous vous intéressez au sujet, je vous propose de vous décrire ce que j’ai pu constater et les démarches manuelles mises en oeuvre.

1) Qui attaque ?

Avec la géolocalisation IP, j’ai obtenu des adresses d’un peu partout dans le monde (Indonésie, Russie, Pays de l’Est…), mais aussi beaucoup la France. Difficile dans ce contexte de savoir si les attaques ne viennent pas aussi de sites infectés qui seraient utilisées comme des machines zombies.

Le niveau de code que j’ai pu voir démontre un certain niveau de technicité, concentré effectivement sur du code vaguement caché, mais surtout, sachant s’insérer dans l’arborescence de WordPress . Ce n’est pas non plus l’oeuvre d’un génie de l’informatique. Les outils d’injection SQL sont facilement trouvables, et ont été adaptés j’imagine par ces codeurs. Personnellement je pense qu’il y aurait plus malin pour véritablement se « cacher dans WordPress », mais je pense que ça n’est pas leur but. Il n’ont pas besoin de faire très malin. La masse des sites WordPress pas forcément bien protégés et pas forcément bien surveillés doit leur suffit.

Bref, il semblerait que tout ceci soit plutôt un empilement de briques (techniques d’injection, obsfucateur de code PHP, robots pour déterminer les sites WordPress). Probablement, ce sont des sets d’outils vendus sur le Dark Web (ou même pas), à destination de phishers ou spammers, qui ont besoin de disposer d’un grand nombre de sites sous leur contrôle pour émettre des mails en masse, des pages web de redirection, et utiliser ainsi de nouvelles adresses IP non blacklistées.

Dans tous les cas, dites-vous que vous n’êtes pas face à un humain, mais à des robots qui vous ont identifié comme une cible potentielle et qui va re-essayer continuellement de vous attaquer. Même une fois éradiqués, votre serveur a été identifié par des scanners comme étant un WordPress. Si en plus l’injection ou l’attaque a fonctionné au moins une fois, alors on peut imaginer que vous êtes notés dans des fichiers avec une petite croix verte et l’annotation « pigeon!. Longtemps après mon nettoyage, même si toutes leurs tentatives échouent, je vois encore les robots buter bêtement sur mon serveur.

2) Désinformer (dans la mesure du possible)

Il y a plusieurs indices qui informeront l’attaquant que vous êtes un WordPress. Il n’est pas nécessaire de lui faciliter la tâche.

2.1) Fichiers d’informations

Les fichiers « readme.html » et « licence.txt » à la racine de votre WordPress comportent des informations de version qui permettrait au robot attaquant d’adapter sa stratégie. Vous pouvez déjà les effacer, mais chaque mise à jour de WordPress vous les remettra.

Je vous conseille donc plutôt d’en interdire l’accès.

Editez le fichier .htaccess à la racine du WordPress et ajoutez:

<Files licence.txt>
	order deny,allow
	deny from all
	allow from none
</Files>
<Files readme.html>
	order deny,allow
	deny from all
	allow from none
</Files>

2.2) Version en <meta>

Par ailleurs, WordPress fournit une information dont je ne vois pas personnellement l’utilité, dans chacune des pages produites:

<meta name="generator" content="WordPress x.x.x" />

2.3) Version des scripts et CSS

WordPress versionne vos scripts et CSS. Ceci a juste pour objectif de permettre aux utilisateurs fréquents de ne pas avoir de problème de cache avec vos scripts et CSS, lors des mises à jour.

Pour ces deux derniers points, je vous propose d’éditer le fichier « functions.php » de votre thème et ajoutez à la fin:

// - remove wordpress generator
// hide the meta tag generator from head and rss
function _filter_disable_wp_version() {
   return '';
}
add_filter('the_generator','_filter_disable_wp_version');
remove_action('wp_head', 'wp_generator');

// - hide version information
// Remove WP version from Styles & scripts : replace with CRC
add_filter( 'style_loader_src', '_filter_no_ver', 9999 );
add_filter( 'script_loader_src', '_filter_no_ver', 9999 );

function _filter_no_ver( $query ) {
	if ( strpos( $query, 'ver=' ) !== false ) {
		global $wp_version;
		$query = remove_query_arg( 'ver', $query );
		$query = add_query_arg('ver', crc32($wp_version.NONCE_KEY), $query);
	}
	return $query;
}

3) Protéger l’authentification

Dans la grande majorité des cas, votre WordPress est certainement administré depuis chez vous, depuis un nombre d’endroit fini par vous, ou par un nombre limité de personnes. Si ce n’est pas le cas, il vous faudra impérativement mettre des systèmes d’authentifications renforcés (double facteur par exemple).

Sinon, si vous avez des adresses IP fixes, vous pouvez protéger l’authentification par adresse IP. Ce n’est pas fiable à 100%, mais cela exigerait un niveau d’agressivité et de technicité qui ne sera certainement pas en oeuvre contre votre site.

Dans le .htaccess à la racine de votre site, ajoutez la section suivante, et mettez autant de « allow from » … que vous avez d’adresse IP utilisées par vous-même et vos administrateurs:

<Files wp-login.php>
	order deny,allow
	deny from all
	# ajoutez ici vos adresses IP publiques
	allow from x.x.x.x
	allow from y.y.y.y
	# etc…	
</Files>

4) Eviter xmlrpc

Ce fichier est à l’origine de nombreux problèmes de failles de sécurité, il y a de très fortes chances que vous n’en ayez pas besoin, si vous ne faites pas interagir votre site WordPress avec des applications Mobile par exemple. Si c’est toutefois le cas, alors il vous faudra mettre des systèmes de protections plus poussés.

Dans le .htaccess à la racine de votre site, ajoutez la section suivante:

<Files xmlrpc.php>
	order deny,allow
	deny from all
	allow from none
</Files>

5) Bloquer la modification et création de fichiers

La méthode peut s’avérer un peu radicale et contraignante à l’usage, mais c’est la plus sûre façon d’empêcher toute modification de fichier, comme on le verra plus loin, ou tout ajout de fichier non voulu sur votre site.

Je vous la conseille si :

– vous gérez (un peu comme moi) votre site assez rarement

– vous ne faites pas confiance dans les plugins de sécurité

Inconvénient important, vous devrez gérer ces droits lors des modifications de fichiers, ou bien lors des mises à jour de WordPress.

Le principe est de mettre votre site entièrement en « Read/only ».

Placez vous à la racine de votre WordPress, et tapez les commandes suivantes (ou copiez/collez):

(si les commandes chmod se plaignent, préfixez la commande par la commande sudo)

#Protéger le site contre l’écriture:
# notez la valeur fournie par la commande stat:
stat -f "%p" wp-content/uploads
chmod -R ugo-w .
chmod -R valeur_stat wp-content/uploads

Si vous utilisez des caches, remettez les droits d’écriture aussi sur ceux-ci.

Avant une mise à jour WordPress, il conviendra de remettre le site en mode écriture:

# Remettre tout le site en mode "écriture autorisée"
chmod -R ugo+w .

Une fois terminé:

# Reprotéger le site
chmod -R ugo-w .
chmod -R valeur_stat wp-content/uploads

Idem si vous voulez travailler sur votre thème (édition CSS, fichiers…), vous pouvez remettre le droit d’écriture sur le dossier des thèmes:

chmod -R ugo+w wp-content/themes/
# reprotéger le dossier de thèmes
chmod -R ugo-w wp-content/themes/

6) Vérifier que vous n’êtes pas infectés

Les manipulations qui suivent impliquant beaucoup de manipulations de fichiers ou de suppression, mettez votre site en mode « écriture autorisée » si vous vous apercevez que vous êtes infectés.

Plusieurs infections sont possibles, que j’ai pu constater (je n’ai pas surveillé mon site pendant au moins 1 an !):

6.1) Vérifier que vous n’avez pas des utilisateurs clandestins

Vérifiez avec votre administrateur WordPress la liste des utilisateurs.

Si vous en avez effectivement, supprimez-les ! Cela signifie que votre WordPress est sensible à l’injection SQL. Il faut vérifier tous vos plugins et extensions (sont ils à jours? sont-ils bien recommandés ?). Mettez bien à jour votre WordPress.

Si quelques jours plus tard (en général 24 ou 48h suffisent), des administrateurs réapparaissent, il va vous falloir monter de niveau. Protégez par adresse IP votre authentification (votre chapitre 3), désactivez vos extensions, et remettez les en place toutes les 48 h, afin de déterminer celle qui est la faille de sécurité. Une fois que vous l’avez identifiée, vous devrez la supprimer ou s’adresser à son développeur.

6.2) Les favicon malicieux

6.2.1) Les favicon avec du code

Le virus positionne des fichiers « favicon » qui sont en fait du code, qui seront discrètement inclus dans des fichiers PHP. Ces fichiers se positionnent au hasard, au fin fond des dossiers, et les scripts PHP les incluant peuvent être n’importe où sur votre site.

Si vous êtes infectés par ces favicons, il faut aussi éradiquer les fichiers qui les incluent.

Pour identifier les favicons douteux:

A la racine de votre site:

find . -name "favicon_*.ico"

Les fichiers sont de la forme « favicon_ » + un codehexadecimal_arbitraire + « .ico »

Exemple:

wp-includes/js/favicon_b8ac3e.ico

Exemple de contenu code du fichier favicon:

Ces fichiers sont à supprimer!

Soit vous les effacez un par un, soit vous pouvez employer la même commande pour le faire massivement:

find . -name "favicon_*.ico" -print -exec rm {} \;

6.2.2) Les include favicon

Ces includes sont placés en tête des fichiers PHP, et incluent le code contenu dans des fichiers favicon. Le nom favicon ne saute pas aux yeux, car il est aléatoirement encodé artificiellement en UTF-8.

La commande include est mise en mode silencieux (au cas où vous auriez effacé le favicon), et généralement encadrée par deux commentaires.

Exemple de code:

/*7015e*/

@include "\x2fs\x72v\x2fd\x61t\x61/\x77e\x62/\x76h\x6fs\x74s\x2fw\x77w\x2el\x65s\x63a\x72n\x65t\x73d\x65n\x61t\x2ec\x6fm\x2fh\x74d\x6fc\x73/\x6ci\x76r\x65d\x6fr\x2da\x74e\x6ci\x65r\x2ff\x61v\x69c\x6fn\x5f9\x61f\x62f\x36.\x69c\x6f";

/*7015e*/

Pour identifier les fichiers:

find . -name "*.php" -exec grep -l -e "@include.*\\\\x" {} \;

Tout le bout de code infectieux (@include et les deux commentaires) est à effacer du fichier, sans supprimer le fichier lui-même.

6.3) Les fichiers de prise de contrôle de votre base de données

Les deux fichiers incriminés sont db_model.php et db_connector.php. Commentés avec beaucoup d’humour « DO NOT REMOVE THIS FILE », ces fichiers prennent allègrement le contrôle de votre base de données.

Les appels se font via des commandes GET avec des paramètres « sort ». On les retrouve dans les logs apache (access.log) avec des valeurs vaguement encodées du paramètre sort.

Les deux fichiers sont effectivement de vrais Open Source. Le db_connector est bien de John Lim, mais il a été modifié pour ne plus être simplement un script destiné à être inclus, mais une page active. Pour en être sûr, regardez à la fin du script, si vous avez des commandes PHP en dehors des classes ou des fonctions:

Exemple de fin de fichier:

    $pager = new ADODB_Pager();
    $pager->render_pagelinks()

Ces fichiers sont à supprimer.

#pour les identifier:

find . -name db_model.php -or -name db_connector.php

#pour les effacer en même temps

find . -name db_model.php -or -name db_connector.php -print -exec rm {} \;

6.4) Les fichiers de cibles de spam

Ces fichiers sont prévus pour être déclenchés par des emails de SPAM envoyés en masse. Si vous en avez, même supprimés, vous aurez encore des tentatives d’accès pendant plusieurs jours.

Il y en a de plusieurs sortes:

6.4.1) Les « alphabet »

Il y en a de plusieurs sortes. Alors pour les repérer il suffit de recherche la séquence « $alphabet » dans le code. Comme c’est un peu léger (il se peu qu’un développeur de plugins aient utilisé cette séquence), il vous faudra aller voir dans le code. Quand « alphabet » est destiné à faire de l’obsfucation douteuse, comme on peut le voir dans les exemples suivants, n’hésitez pas.  

Exemple de code1:

Tout ce bout de code est à effacer du fichier, sans supprimer le fichier lui-même.

Exemple de code 2:

Dans ce cas, le fichier ne contient que le code infectieux, il est à supprimer.

#pour les identifier

find . -name "*.php" -exec grep -l -e "\\$alphabet =" {} \;

6.4.2) Les « base64 »

Tout le code est en base64, d’où le nom que je donne ici.

Exemple de code:

Pour les identifier:

grep -r -e "create_function.*base64_decode" .

Ces fichiers sont à supprimer.

6.4.3) Générateur de redirection (htaccess/Google)

Je le nomme comme cela car il y a un test étrange avec le cookie ‘google’ dont je ne vois pas bien l’intérêt.

Ce code change les droits du fichier .htaccess, et crée apparemment des fichiers de redirection vers d’autres sites.

Exemple de code:

# pour les identifier

grep -r -e "\$_COOKIE.*google" .

Ces fichiers sont à supprimer!

6.5) Les générateurs de fichiers

Ces fichiers génèrent des blocs entiers de code, qu’il va falloir supprimer. Ils constituent un dossier au nom improbable qui devrait vous paraître suspect. (voir ci-après).

Ces fichiers sont en quelque sorte des auto-dezipeurs. Ils contiennent leur contenu ZIP dans un base 64, qu’ils vont installer tranquillement. Si vous supprimez les fichiers ainsi générés q-et que vous laissez le générateur, il se re-génèrera. En effet, un robot sera chargé du déclenchement.

Je pense que leur stratégie est : poser un générateur, le laisser un bon moment. Passé ce long moment, un robot appel le générateur. S’il n’est pas rejeté par un 404, c’est bingo. Le site est mal protégé, donc on va pouvoir l’utiliser pendant un bon moment… Les fichiers sont donc générés, et le spam faisant référence à ces pages générées peut commencer.

Exemple de code:

#Pour les identifier

grep -r -e "file_put_contents.*\.zip" .

Ces fichiers sont à supprimer! Mais vraisemblablement, ils ont générés une arborescence de fichiers, correspondant au nom que l’on voit dans file_put_contents. Supprimez les aussi.

6.6) Les GLOBALS-GLOBALS

Je les appelle comme cela car les petits malins utilisent une obsfucation de code basée sur les $GLOBALS. Ca pique les yeux quand on regarde le code, ce qui laisse à supposer que l’on peut les supprimer relativement sans se tromper (ou alors c’est du code qui mérite d’être effacé!).

Exemple de code:

# pour les identifier

grep -l -r "\$GLOBALS\[\$GLOBALS" .

Ces fichiers sont à supprimer!

6.7) Les redirecteurs

Placés par une des précédentes engeance, selon toute vraisemblance, ils sont là pour émettre une redirection (redirection ou iframe). Comme votre site n’est pas encore identifié par les antispams MAIL, ils s’appuient sur votre site pour émettre la page sur votre site, avec la redirection vers leur site (phishing, vente de pilules, etc…).

Alors cette fois ce sont de simples pages sans code. Il ne vont pas faire grand mal, si ce n’est que votre site est utilisé à des fins malhonnêtes, et qu’il risque à terme par être blacklisté.

Exemple de page 1:

Exemple de page 2:

Ces fichiers sont à supprimer!

Pour les identifier, utilisez le script fourni ci-après.

7) Script de vérification

Je mets à disposition un petit script PHP qui va lancer toutes les vérifications énoncées précédemment (sauf 6.1). Exécutez-le au moins une fois sur votre site.

Télécharger : check_virus_wordpress.php.zip

S’exécute simplement dans votre dossier WordPress en mode commande, ou préfixé de la commande PHP.

Conclusion

N’hésitez pas à me faire part de vos commentaires. Si vous trouvez d’autres virus, je vous invite à m’envoyer les fichiers.

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *