Désinfection WordPress : distinguer code légitime et code malveillant

On confond souvent la “désinfection WordPress” avec un geste unique: supprimer des fichiers suspects et espérer que tout rentre dans l’ordre. En pratique, la réalité ressemble davantage à un travail de lecture et d’autopsie. WordPress est un socle vivant, extensible, avec des centaines de combinaisons possibles entre thèmes, plugins, scripts tiers, optimisations caches et intégrations marketing. Dans ce contexte, le vrai défi n’est pas seulement de trouver du code malveillant. C’est surtout de distinguer ce qui est légitime, parce que “ça ressemble à du code”, de ce qui est réellement conçu pour compromettre votre site.

Cette distinction demande une méthode. Elle demande aussi du sang-froid, parce que le risque est double: soit vous laissez passer un morceau infecté, soit vous cassez une partie légitime du site en supprimant trop vite.

Le point de départ: ce que l’on appelle “malware” sur WordPress

Quand on parle de code malveillant sur WordPress, on imagine souvent un fichier qui “exploit” directement une vulnérabilité. C’est possible, mais ce n’est pas le scénario le plus fréquent dans les incidents du quotidien.

Beaucoup d’infections sont plus discrètes. Elles ajoutent une porte dérobée à un endroit banal, elles déplacent du contenu pour injecter du spam, elles détournent des formulaires, ou elles “préparent le terrain” pour récupérer des informations. D’autres fois, le site n’est pas cassé, il est juste détourné, au rythme des visites.

Un détail important: un site WordPress peut sembler propre sur le front, tout en étant compromis en arrière-plan. Et inversement, on peut trouver du code “bizarre” sur un thème, un plugin, ou un script chargé au chargement de page, sans que ce code soit malveillant.

D’où l’idée centrale: distinguer le légitime du malveillant implique d’observer le comportement, pas seulement la forme.

Pourquoi distinguer le légitime du malveillant est plus difficile qu’on ne le pense

WordPress charge un ensemble d’éléments qui se ressemblent parfois. Du code PHP dans des fichiers de thème, du code JavaScript côté navigateur, des hooks, des filtres, des actions. Des constructeurs de page peuvent générer du code volumineux. Un plugin d’optimisation peut inline du CSS, minifier des scripts, injecter des morceaux conditionnels.

Résultat: certains motifs “typiques” de l’attaque peuvent aussi exister dans du code légitime. Prenons un exemple concret, rencontré lors d’une désinfection. Un client avait remarqué un fichier PHP dans un dossier de cache. Il contenait une suite de caractères qui, à première vue, évoquait un obfuscateur. En réalité, c’était un contenu produit par un plugin de compression et stocké pour servir plus vite les pages. Ce que le plugin faisait était cohérent, et surtout le fichier n’était pas exécutable de manière détournée. Une fois le cache reconstruit, le contenu est devenu régulier.

L’observation clé a https://gardewp.fr/nettoyage-malware-wordpress/ été simple: ce “code suspect” n’apparaissait pas comme une logique exécutée pour exfiltrer ou modifier des pages. Il participait au rendu.

Ce genre de nuance est exactement ce qui rend la désinfection délicate.

Commencer par la cartographie, pas par la suppression

Avant de toucher aux fichiers, j’aime faire un inventaire orienté “risque d’exécution”. L’idée: si vous supprimez un fichier sans comprendre où il est utilisé, vous pouvez casser un plugin légitime ou laisser une autre entrée malveillante intacte.

Sur un site compromis, vous devez vous poser des questions comme:

    Qu’est-ce qui est arrivé récemment? Mise à jour, installation d’un nouveau plugin, changement de thème, modification de rôles utilisateurs, création d’un utilisateur “tech”? Quel est le symptôme réel? Spam, redirections, pages déformées, fausses formulaires, ralentissements, téléchargements inattendus, montées en charge sur certains endpoints? Est-ce un incident ponctuel ou un comportement persistant? Les mêmes pages sont-elles toujours modifiées à chaque chargement?

Cette phase peut sembler “administrative”, mais elle évite des erreurs coûteuses. J’ai déjà vu des désinfections repartir sur une base trop large, en supprimant des dossiers entiers “par précaution”, puis en redécouvrant des fonctionnalités cassées uniquement après la remise en ligne.

Les signaux qui doivent alerter, sans tomber dans la parano

Il n’existe pas de signature universelle, mais certains signaux reviennent souvent dans les cas malveillants sur WordPress. Ils ne prouvent pas à eux seuls. Ils orientent vers une vérification plus fine.

Par exemple, un fichier qui est modifié à une date proche du début de l’incident, alors qu’il n’a jamais changé depuis des mois, est un candidat naturel à l’analyse. De même, un script qui n’est pas documenté, placé dans un endroit inattendu, et qui charge des ressources distantes avec des paramètres incohérents, mérite un regard sérieux.

À l’inverse, du code chargé depuis un CDN reconnu peut être légitime, surtout s’il correspond à un plugin officiel ou à une intégration connue. La clé, encore une fois, est la cohérence.

Voici deux catégories de signaux qui méritent une attention particulière.

1) Exécution “hors contexte”

Un code malveillant doit souvent s’exécuter au bon moment, au bon endroit. Sur WordPress, ce moment est fréquemment lié à un hook, à un fichier chargé, ou à une condition d’exécution.

Les cas typiques incluent:

    une inclusion dynamique de fichiers selon une condition obscure un appel à des fonctions qui manipulent des URLs, exécutent du code, ou lisent/écrivent des fichiers sans logique métier claire une altération de contenu via un filtre sur le rendu, avec des patterns “magiques” difficiles à justifier par la fonctionnalité

Le point pratique ici: si un morceau de code n’a aucune raison d’être dans le flux de rendu d’une page, il faut le traiter comme suspect tant qu’on ne peut pas démontrer le contraire.

2) Obfuscation et “chargement différé”

De nombreux scripts malveillants utilisent une forme d’obfuscation, parfois très simple, parfois plus sophistiquée. Le but est de rendre la lecture difficile et d’éviter une détection basée sur la présence de mots-clés.

Mais attention: l’obfuscation n’est pas un crime. Certains plugins minifient, packent ou transforment le code JavaScript pour réduire la taille et accélérer le chargement. Certains scripts peuvent aussi encoder des données pour des raisons de performance ou de compatibilité.

Ce qui change la donne, c’est la finalité: transformation au service du rendu, ou transformation pour masquer une logique d’accès, de redirection, d’exfiltration, ou de modification de contenu.

Méthode pratique: examiner la finalité, puis remonter l’entrée

La manière la plus fiable de distinguer le légitime du malveillant consiste à remonter à la “chaîne”:

Qu’est-ce qui est observable sur le site? Quel élément a déclenché cet effet? Quel fichier ou quel hook est impliqué? Quelles parties sont légitimes et lesquelles ne le sont pas? Quelle est la persistance, c’est-à-dire comment cela revient après suppression partielle?

Au lieu de chercher uniquement “des signatures de malware”, vous cherchez des liens causaux.

Exemple vécu: injection de contenu seulement sur certaines pages

Sur un site e-commerce, le client voyait des sections ajoutées à l’accueil, pas ailleurs, et uniquement certains jours. Les scanners automatiques signalaient un fichier dans le dossier racine du thème. En ouvrant le fichier, on trouvait un bloc de code conditionnel basé sur des variables d’environnement.

Le piège classique était de supprimer le fichier, ce qui aurait cassé la mise en page. La vraie approche a été de déterminer ce que le code conditionnel faisait exactement, et surtout quand il s’activa. On a ensuite identifié que la logique en cause chargeait des extraits externes et réécrivait une portion du contenu final. À ce moment-là seulement, la suppression ciblée a été possible sans endommager le reste du thème.

Ce qui a fait gagner du temps, c’est de ne pas traiter le fichier comme “bon” ou “mauvais” avant d’avoir compris la finalité.

Les endroits où l’on trouve le plus souvent des altérations

Sans prétendre à une liste exhaustive, certains emplacements reviennent souvent, parce qu’ils sont faciles à exploiter et parce que WordPress y est extensible.

On pense aux fichiers de thèmes et de plugins, mais aussi:

    aux fichiers à la racine à certaines sections du contenu stocké (par exemple base de données, options, métadonnées) aux comptes utilisateurs et aux rôles à des scripts chargés via des hooks et des événements d’administration

Si le site est compromis, l’infection cherche généralement un point de persistance. Cela peut être un fichier modifié, mais aussi un utilisateur créé ou un paramètre stocké.

C’est la raison pour laquelle une désinfection efficace ne se limite pas aux fichiers. Les bases de données peuvent contenir des “pistes” de persistance, comme des options modifiées ou des contenus injectés.

Concrètement, comment trier: légitime ou malveillant

J’utilise un raisonnement en deux temps: d’abord, je regarde ce que fait le code, pas comment il s’affiche. Ensuite, je vérifie la cohérence avec le contexte du site.

Voici un petit protocole, suffisamment “léger” pour être appliqué sans outillage complexe, mais assez strict pour limiter les erreurs.

    Vérifier la date et le propriétaire des fichiers modifiés, puis comparer au calendrier des changements connus (mises à jour, nouveaux plugins, accès admin). Rechercher les inclusions et chargements dynamiques: un “include” ou un “require” placé de manière inattendue est un signal fort, surtout s’il pointe vers un chemin non standard. Identifier les fonctions et opérations: lire un fichier local, exécuter une commande, faire des appels réseau vers des domaines non liés au site, modifier du contenu de sortie, tout cela se traite différemment. Confirmer le rôle dans le flux WordPress: l’exécution est-elle rattachée à un hook pertinent? Est-elle déclenchée uniquement dans des circonstances réalistes? Vérifier la persistance: après nettoyage, observe-t-on un retour identique, ce qui indiquerait une autre entrée (base de données, compte admin, autre fichier).

Cette approche est exigeante, mais elle évite la suppression “au feeling”. Et quand vous supprimez, vous supprimez quelque chose dont vous comprenez l’effet.

Cas fréquents où le “suspect” n’est pas un malware

Il y a des situations où des éléments ressemblent à une infection, mais ne le sont pas.

Thèmes et plugins générés ou packagés

Certaines extensions intègrent du code “compact”, avec des chaînes encodées. C’est parfois le résultat d’un build moderne, minification, bundling, ou génération à partir d’un éditeur.

Dans ces cas, le code est cohérent avec l’outil utilisé, et les fonctions restent alignées avec la fonctionnalité du plugin.

Cache et fichiers temporaires

WordPress produit énormément de cache. Certains plugins écrivent des fichiers de service. Si vous analysez des fichiers temporaires sans vérifier leur usage, vous pouvez tomber sur des “formes” suspectes alors qu’il s’agit de contenus générés.

Mon conseil pratique: reconstruire ou purger certains caches, puis observer ce qui revient. Si le contenu “bizarre” disparaît après purge et ne revient pas, c’est souvent un faux positif.

Permissions et environnements

Parfois, un script légitime échoue, déclenche une erreur, puis on attribue l’erreur au hack. Il faut distinguer l’incident d’exécution (PHP error, memory limit, incompatibilité de versions) de la compromission.

Le contexte ici est important: une incompatibilité peut provoquer des comportements inattendus sans intention malveillante.

Cas où le code ressemble au légitime, mais ne l’est pas

Le revers est tout aussi réel. Un malware peut imiter un style propre, utiliser des structures propres, et rester lisible, mais il aura une finalité étrangère.

Un motif qui trompe souvent: la présence de hooks WordPress légitimes. Un code peut utiliser un filtre standard, et c’est précisément là que la page peut être modifiée. Le malware ne cherche pas forcément à être caché, parfois il vise juste à s’intégrer.

Autrement dit, la question “est-ce que le code ressemble à WordPress?” n’est pas suffisante. La bonne question est: “pourquoi ce code est là et quel effet produit-il sur un rendu réel?”.

Deux erreurs qui aggravent les infections

Il y a des façons de “désinfecter” qui compliquent la tâche.

Réinstaller sans comprendre le vecteur d’entrée

Réinstaller WordPress et quelques fichiers peut supprimer la surface, mais si le compte admin compromis existe encore, ou si un nouveau fichier est réinjecté depuis une autre source, l’incident revient.

J’ai déjà vu des sites qui étaient remis en ligne en quelques heures, puis re-vérifiés le lendemain avec la même infection. La cause n’était pas le fichier effacé, c’était la persistance côté accès, ou un paramètre base de données oublié.

Supprimer trop agressivement

Quand un fichier est modifié, la tentation est de supprimer tout ce qui touche au thème ou au plugin. Sauf que sur WordPress, il existe de nombreux points d’adaptation, et certains fichiers “apparemment non essentiels” portent des styles, des traductions, des options de performance.

image

Si vous supprimez, vous devez pouvoir prouver qu’une partie du comportement n’a pas d’impact. Sans ça, le site peut être “décomposé”, et la désinfection devient une reconstruction.

Créer un plan de remédiation qui limite les dégâts

Une désinfection sérieuse demande aussi une discipline: isoler, restaurer proprement, puis vérifier avant de rouvrir.

Je préfère travailler en trois temps, même si l’urgence pousse souvent à faire plus vite.

1) Isoler et figer l’état: éviter que la charge malveillante continue, éviter que de nouvelles modifications arrivent pendant l’analyse. 2) Restaurer une base fiable: reconstruire à partir de sources propres quand c’est possible, en remplaçant uniquement ce qui a été compromis. 3) Vérifier le comportement: pas seulement “est-ce que ça s’affiche”, mais “est-ce que ça se modifie”.

Il faut aussi intégrer une vérification côté comptes. Les rôles et les comptes peuvent être le point de départ, surtout si une porte d’entrée faible a été gardée.

Le piège des scanners automatiques: utiles, pas suffisants

Les outils de scan et les extensions antivirus WordPress peuvent aider. Ils repèrent parfois des patterns, parfois des modifications connues. Mais ils peuvent aussi produire des faux positifs, en particulier avec du code packagé.

Le meilleur usage que j’ai vu consiste à considérer les alertes comme des “hypothèses”, pas comme des verdicts.

Quand un scanner signale un fichier, je traite cela comme une invitation à analyser la finalité et le contexte. Si la logique est cohérente, que les fonctions servent la fonctionnalité attendue, et que le comportement ne correspond pas à une injection, je peux classer l’alerte en “probable faux positif” et documenter la décision.

Sans documenter, l’équipe perd du temps le jour où il faut réitérer une vérification.

Comprendre la “persistance”: le vrai cœur de la désinfection

Un malware qui veut survivre a besoin de persister. Sur WordPress, la persistance peut être:

image

    un fichier modifié qui se relance via un hook une option en base de données changée un compte admin nouvellement créé un scheduled job ou une tâche programmée un mécanisme de mise à jour mal contrôlée

Le problème est que la persistance ne se contente pas de créer une seule surface. Souvent, elle crée une chaîne. Si vous nettoyez un maillon, l’autre relance le problème.

C’est pour cela que distinguer légitime et malveillant ne suffit pas si vous ne cherchez pas ensuite le mécanisme de retour.

Remettre en ligne: comment s’assurer que c’est propre sans tout casser

Avant de réactiver le site, je cherche des preuves de “non-régression”.

Cela peut être simple, par exemple vérifier les pages les plus exposées, les pages où une injection était vue, et le comportement des formulaires. Mais ça doit aussi toucher aux endroits où la compromission s’exécutait.

Il est fréquent que l’équipe se limite à une page d’accueil et à un test de connexion. Or, beaucoup d’infections sont conditionnelles, ou déclenchées seulement après un temps, selon un type de visiteur, ou via une requête précise.

Un test prudent consiste à rejouer le scénario qui déclenchait l’incident: recharger les pages concernées, vérifier le rendu, inspecter les ressources chargées, et observer les logs applicatifs quand c’est possible.

Une méthode de tri rapide, pour limiter le risque en cas d’urgence

Quand on n’a pas des heures devant soi, il faut quand même une discipline. Voici une approche courte pour cadrer la décision, en gardant à l’esprit que la prudence vaut mieux que la suppression aveugle.

    Si un fichier modifié est identique à une version “attendue” pour le thème ou le plugin, et qu’il n’introduit aucune logique de redirection, d’exfiltration ou de modification de contenu, il est souvent classé “légitime à vérifier”. Si un fichier modifié introduit des inclusions dynamiques vers des chemins non standard, ou des appels réseau non cohérents, il est classé “malveillant probable”. Si la logique est difficile à lire, mais que le comportement est exactement celui du plugin (par exemple génération de styles, routines de cache), je ne supprime pas directement. Je purge et je reconstruis, puis j’observe. Si la compromission revient après suppression, la persistance est ailleurs, probablement base de données ou accès. On ne peut pas conclure sur un seul fichier.

Cette méthode n’est pas “automatique”. Elle sert à éviter de courir dans la mauvaise direction.

Le facteur humain: accès, mots de passe, et hygiène de déploiement

Le code malveillant n’existe pas dans le vide. Souvent, il s’implante parce qu’un accès a été compromis ou parce qu’une mise à jour n’a pas été faite.

Je n’insiste pas sur les recommandations générales, je préfère des actions concrètes qui ont un impact réel:

    comparer les comptes administrateurs actuels avec ceux attendus vérifier les rôles et les nouveaux utilisateurs apparus récemment contrôler la chaîne de déploiement, surtout si des plugins tiers sont installés manuellement retirer ce qui n’est pas nécessaire, thème et plugins abandonnés compris

Quand une infection a eu lieu, la désinfection doit aller de pair avec une consolidation. Sinon, on désinfecte une plaie, mais on laisse la cause respirer.

Travailler avec prudence sur le code: l’endroit où les erreurs coûtent le plus

Il y a un endroit où les décisions “au couteau” sont risquées: la modification manuelle de fichiers pour enlever un bloc suspect. En théorie, on peut corriger une injection en supprimant quelques lignes. En pratique, il est facile de toucher à un morceau de code utile, surtout si l’infection a été intégrée dans une fonction plus large.

Un choix plus sûr est souvent de remplacer le fichier complet par une version propre, puis de réappliquer uniquement les personnalisations nécessaires. Oui, c’est plus de travail au départ, mais cela réduit les “zones grises”.

Le bon compromis dépend de votre contexte, de la présence ou non de personnalisations, et de votre capacité à restaurer depuis une source fiable.

Quand consulter un spécialiste devient rationnel

Tout le monde ne doit pas forcément externaliser. Mais si vous observez plusieurs symptômes simultanés (redirections, injection de contenu, comptes admin suspects, charge anormale, domaines inconnus), et si les traces sont difficiles à interpréter, un audit externe peut être le choix le plus rentable.

Le critère qui compte n’est pas le budget, c’est le temps perdu à faire des allers-retours. Une désinfection mal cadrée consomme des heures, puis laisse encore du risque résiduel.

Si l’équipe interne a déjà “réparé” une fois sans résolution totale, je considère que l’investissement dans un diagnostic plus structuré peut éviter une deuxième désinfection.

Ressources internes pour mieux trier la prochaine fois

Après une désinfection, il est utile de garder des repères pour la fois suivante. Pas besoin d’un grand process, juste des traces.

Je recommande au minimum de conserver:

    la liste des plugins et thèmes installés au moment du problème les dates de modifications, au moins approximatives le détail de ce qui a été supprimé ou remplacé ce qui a été testé avant remise en ligne

Ce sont des éléments simples, mais ils permettent de comparer la prochaine alerte et de distinguer plus vite ce qui est “normal pour votre site” de ce qui s’en écarte.

Une dernière idée, souvent oubliée: la propreté ne se juge pas une seule fois

Un site peut paraître sain pendant une journée, puis réagir ensuite. Les infections peuvent aussi activer leurs mécanismes seulement sous certaines conditions.

Distinguer le code légitime du code malveillant demande donc une observation répétée, pas un verdict unique. Quand vous testez, vous cherchez à confirmer l’absence de persistance, et surtout l’absence de modification future.

C’est ce qui transforme la désinfection en restauration durable.

Si vous voulez, décrivez-moi votre situation (symptômes, plugins récents, ce que le scanner a trouvé, et où exactement le code “suspect” se trouve). Je peux vous aider à formuler une méthode de tri adaptée, avec des critères de décision plus précis, sans supprimer à l’aveugle.