Quand un site WordPress commence à se comporter de façon étrange, la première minute est souvent la plus précieuse. Pas parce que vous allez “magiquement réparer”, mais parce que vous voulez observer avant de casser le reste. Un cheval de Troie WordPress ne se contente presque jamais d’un seul endroit. Il cache, il persiste, il tente de brouiller l’analyse. Et dans beaucoup d’incidents récents, le point commun, c’est la présence de blocs de code compressés, encodés en base64, puis exécutés à la volée via eval.
Je l’ai vu sur des sites de TPE et aussi sur des blogs à fort trafic. Le scénario se ressemble: un trafic qui grimpe sans raison, des redirections vers des pages externes, des fichiers qui apparaissent en dehors des périodes habituelles de déploiement, et parfois des comptes administrateurs qui “reviennent” même après suppression. Dans ce contexte, savoir repérer rapidement un code base64 et un eval malveillant, c’est gagner des heures, parfois des jours.
Les signes qui font penser à un eval et à du base64
Tous les malwares WordPress ne se ressemblent pas, mais leurs habitudes sont assez récurrentes. Le pattern le plus parlant, c’est une portion de PHP qui tient en quelques lignes, souvent très “lisible” à l’envers.
Vous voyez typiquement un code qui ressemble à ceci, ou à une variante proche:
- une chaîne longue de caractères (souvent du base64) concaténée à la volée; une fonction d’encodage/décodage utilisée pour transformer cette chaîne; puis une exécution dynamique via eval(...), parfois après un gzinflate ou une décompression.
Le piège, c’est que ce genre de code est rarement écrit de façon directe et “propre”. Le malware essaye de réduire la signature. Il découpe la chaîne, il mélange des appels de fonctions, il masque des chaînes et des chemins. Parfois, il ne met pas explicitement eval, mais exécute le résultat ailleurs via une mécanique similaire. La présence d’un bloc base64 très long dans un fichier PHP anormal est souvent le meilleur signal, surtout si le fichier n’appartient pas à un thème ou à un plugin que vous connaissez.
Autre indice fréquent: les heures de modification. Si vous regardez les timestamps sur un serveur partagé ou https://gardewp.fr/ sur un VPS, et que vous remarquez un fichier modifié en pleine nuit, un jour où personne n’a déployé, ça vaut une enquête immédiate. Sur un site que j’ai aidé à nettoyer, le code malveillant était niché dans un fichier “banal”, dont la date de modification ne correspondait à aucune mise à jour WordPress ni à aucun plugin. Ça a réduit la recherche à un petit périmètre.
Comprendre le mécanisme sans s’y noyer
Le base64, en soi, n’est pas forcément malveillant. Il sert à transporter des données sous une forme “texte”. Ce qui devient inquiétant, c’est le combo:
Un contenu base64 stocké dans un fichier PHP; Une fonction PHP le décode; Une exécution dynamique du contenu décodé, souvent avec eval.Le but est simple: éviter de laisser une charge utile PHP claire dans le fichier. Au lieu d’un code lisible, vous obtenez une “enveloppe” qui ne devient du PHP exécutable qu’au moment où le serveur interprète le fichier, souvent lors d’une visite.
Ce modèle est pratique pour les attaquants car il complique l’inspection rapide, sans même que vous ayez à lancer d’outils lourds. Si vous savez chercher les signatures de décodage et d’exécution, vous pouvez souvent identifier le point d’entrée ou, au minimum, les fichiers qui portent la charge.
Repérer les fichiers suspects dans votre base de code
La première erreur que je vois, c’est de chercher uniquement dans le dossier wp-content. Un malware peut s’infiltrer ailleurs: dans des fichiers de thème, dans des fichiers muets sous wp-includes, dans des fichiers racine, ou encore via des templates et des chargeurs.
La deuxième erreur, c’est de “nettoyer” trop vite sans vérifier ce qui tourne réellement. Copier-coller un nettoyage peut casser le site, mais surtout effacer les preuves utiles. Donc l’approche la plus fiable est: isoler, observer, puis corriger.
Vous pouvez commencer par repérer les anomalies qui reviennent souvent dans les cas de eval malveillant:
- des fichiers PHP contenant des chaînes base64 extrêmement longues; l’apparition de eval( dans des fichiers qui ne sont pas issus de votre code ou de vos dépendances; des fonctions de décompression utilisées à des endroits non attendus (par exemple avec des flux qui ressemblent à des charges compressées); des fichiers qui ne devraient pas exister, ou des fichiers dont le nom n’évoque rien de votre architecture.
Un point pratique qui fait gagner du temps: si vous avez accès à votre interface d’hébergement, regardez aussi les “fichiers modifiés” et les logs d’erreurs. Mais le plus fiable reste de comparer les arborescences à une référence saine, idéalement celle d’une sauvegarde antérieure.
Exemple de repérage rapide côté fichiers
Imaginons que vous soupçonniez un plugin ou un thème. Vous ouvrez le fichier suspect et vous trouvez une section où une chaîne longue est passée dans un décodage avant d’être “jouée” par eval. À ce stade, vous n’essayez pas encore de “comprendre toute la charge”. Vous voulez d’abord:
- localiser précisément l’emplacement exact dans le fichier; vérifier s’il y a d’autres eval ailleurs; relever le nom de la fonction qui exécute et, si possible, le chemin vers où la charge utile finit par écrire ou inclure des fichiers.
Sur un cas concret, la charge base64 elle-même contenait un second mécanisme d’écriture de fichiers. Tant que je ne l’avais pas compris, on pensait que supprimer le fichier initial suffisait. En réalité, une deuxième étape recréait la persistance dans un autre dossier.
Décrypter pour analyser, sans aggraver
Une fois que vous avez trouvé un bloc base64 et un eval, votre instinct peut être de copier-coller et d’exécuter le code “pour voir”. Je déconseille. Même sur un environnement local, vous ne savez pas ce que la charge peut déclencher. Elle peut effectuer des requêtes HTTP sortantes, ouvrir des connexions, créer des comptes, modifier des options WordPress ou déposer d’autres fichiers. Le simple fait de “décoder puis exécuter” sur une machine connectée peut transformer un incident local en incident généralisé.
À la place, je préfère une analyse statique, et quand il faut absolument exécuter, le faire dans un environnement fermé, sans accès au réseau, et avec une instrumentation claire. Mais pour l’objectif “enlever virus WordPress” de façon efficace, on n’a pas toujours besoin d’exécuter la charge utile.
Ce que vous pouvez faire utilement:
- Extraire la chaîne base64 à partir du fichier suspect. Vérifier sa taille, car des tailles très grandes (souvent des centaines de kilooctets ou plus selon la charge) sont typiques des malwares plus récents. Observer les transformations autour: décodage direct, décompression, concaténation. Identifier si le résultat décodé ressemble à du code PHP (on peut souvent reconnaître des débuts de structure, <?php, des appels de fonctions, des références à des fichiers). </ul> Une fois que vous avez ces éléments, vous pouvez décider: supprimer le fichier et désactiver les composants associés, ou d’abord remonter la chaîne de compromission. La méthode de nettoyage la plus sûre: casser la persistance, puis restaurer En pratique, enlever virus WordPress proprement ne consiste pas à “effacer un fichier”. Les malwares WordPress veulent que quelque chose les relance. Donc vous devez agir à deux niveaux: stopper l’exécution actuelle et supprimer la persistance. Si vous avez une sauvegarde saine datée d’avant l’incident, c’est souvent la voie la plus robuste. Vous restaurez, puis vous chassez les différences introduites entre la dernière version saine et l’état compromis. Ce travail peut être long, mais il évite de laisser une “bombe” qui se déclenche plus tard. Si vous n’avez pas de sauvegarde récente, vous pouvez quand même avancer, mais il faut un peu plus de discipline: désactiver les thèmes et plugins non essentiels, supprimer les fichiers manifestement malveillants, remplacer les fichiers WordPress core par une version fiable, puis vérifier base de données, droits et comptes. Une checkliste courte avant toute suppression Avant de toucher à des fichiers, faites un mini-cadrage. Ce n’est pas une cérémonie, c’est une manière d’éviter les erreurs qui coûtent cher.
- Faites une copie de vos fichiers et de votre base de données (au moins un dump) si c’est possible. Déconnectez le site des actions risquées (désactivez les plugins non essentiels en mode maintenance, si vous le pouvez). Notez les fichiers qui contiennent base64 long et eval, avec leurs chemins exacts. Vérifiez rapidement qui a des droits admin, et si de nouveaux utilisateurs existent. Contrôlez les logs d’accès et d’erreurs autour de la période d’apparition.
- modifier un fichier existant dans un thème ou un plugin; ajouter un fichier “camouflé” dans un dossier attendu; modifier la base de données pour injecter du code via un champ option ou une zone de template.
- les options WordPress; des métadonnées plugin; des contenus de pages ou d’articles (par exemple dans un champ qui injecte du PHP si mal géré); des hooks ou des filtres ajoutés par des snippets.
- sandbox sans accès réseau, ou réseau strictement contrôlé; aucune exécution automatique sur un serveur connecté à la prod; capture des fichiers et logs du sandbox pour reconstituer la chaîne.
- un plugin non mis à jour; un thème modifié sans être surveillé; un mot de passe faible, ou réutilisé; une configuration FTP ou SSH trop large; une faille d’injection ou une mauvaise gestion des droits.
- Mettre à jour WordPress, thèmes et plugins, et supprimer ce qui n’est pas utilisé. Contrôler les comptes administrateurs et supprimer tout ce qui ne vous appartient pas. Vérifier les permissions fichiers et dossiers, et corriger toute dérive. Activer un pare-feu applicatif ou au minimum un filtrage robuste des requêtes suspectes. Mettre en place une surveillance d’intégrité (au moins sur les fichiers PHP clés).
- Vous supprimez le fichier déclencheur, mais pas la source de la persistance. Vous remplacez des fichiers sans vérifier qu’un plugin compromis n’était pas à l’origine. Vous corrigez les fichiers, mais vous laissez en base un champ injecté qui reconstitue du code. Vous changez un mot de passe admin sans vérifier les autres comptes. Vous réinstallez sans contrôler que le vecteur initial, typiquement un plugin vulnérable, est encore là.
- ne plus contenir eval dans des fichiers inattendus (ou à minima dans des zones que vous attendez); ne plus avoir de chaînes base64 suspectes dans les fichiers PHP; ne plus déclencher de nouvelles écritures anormales; conserver la liste des utilisateurs et la configuration sans réapparitions.