Quand un site WordPress “semble” infecté, on pense vite au fichier corrompu, au thème bizarre, ou à un exécutable planqué. Dans la pratique, la porte d’entrée la plus fréquente reste ailleurs: un plugin, parfois un plugin “de façade” qui ne se fait remarquer qu’après coup, et, surtout, ses dépendances.
Je me suis retrouvé plusieurs fois face à des nettoyages qui ressemblaient à un jeu de piste. On supprime une extension, tout a l’air de rentrer dans l’ordre, puis quelques heures plus tard les mêmes symptômes reviennent. La cause n’était pas “le virus” au sens classique, mais une dépendance indirecte, un plugin compagnon installé sans qu’on s’en rende compte, ou un chargement différé qui n’apparaissait qu’à certains moments, par exemple quand un auteur publie, quand un cron tourne, ou quand un visiteur tombe sur une page précise.
L’objectif ici est simple: comprendre comment vérifier les extensions et leurs dépendances pendant un nettoyage de suspicion de compromission, et comment éviter les pièges les plus courants.
Le problème n’est pas toujours l’extension “coupable”, mais sa chaîne
Sur WordPress, une extension n’existe presque jamais seule. Elle s’appuie sur des bibliothèques internes, des fichiers dans includes/, des ressources chargées en front (JS, CSS), et parfois des composants fournis par d’autres extensions. Elle peut aussi s’adosser à des thèmes, à des règles de réécriture, à des hooks, et à des tâches planifiées.
Lorsqu’une attaque vise l’infrastructure applicative, elle cherche souvent l’endroit où elle peut obtenir une exécution durable. Les plugins offrent ce cadre, parce qu’ils sont chargés par WordPress au moment opportun. Même si vous ne retrouvez pas tout de suite un fichier “suspect”, vous pouvez voir des signatures de chargement, des URLs externes, des modifications de hooks, ou des requêtes internes déclenchées au runtime.
La clé du nettoyage, c’est de ne pas se limiter à “désactiver puis supprimer”. Désactiver coupe la fonctionnalité, mais ne prouve pas l’absence de persistance ailleurs. Supprimer efface le code, mais peut aussi enlever un indice précieux si vous n’avez pas d’abord conservé une trace.
Première observation utile: “qui charge quoi” avant de toucher au site
Avant de modifier quoi que ce soit, prenez l’habitude de questionner le site en conditions réelles. Ce que je fais, c’est regarder les symptômes et leurs patterns: pages touchées, moments où ça s’active, comptes concernés, déclencheurs.
Ensuite, je vérifie le chargement côté WordPress. Sans outils lourds, on peut déjà obtenir des informations via l’administration, l’accès aux fichiers, et les logs serveur. Selon votre hébergement, vous pouvez avoir:
- logs d’accès web (URLs appelées, codes, fréquence), logs erreurs PHP (stack traces, warnings), logs applicatifs (si un plugin ou un module les produit), événements de planification (cron, tâches WP, parfois dans le panneau d’hébergement).
Le but n’est pas de “diagnostiquer à 100 pour cent” sur place, mais de trouver où la perturbation se concentre. Si vous voyez que seules certaines pages affichent du contenu externe, cela oriente souvent vers un plugin qui filtre certains templates, ou qui ajoute du code dans le head ou dans le footer.
À ce stade, le plus important est de figer l’état. Si vous effacez tout immédiatement, vous perdez la possibilité de comparer “avant” et “après”.
Construire une liste de suspects: extensions activées, mais aussi inactives
Dans un nettoyage de virus WordPress, on se focalise souvent sur les extensions activées. C’est logique, car ce sont elles qui exécutent du code. Mais j’ai déjà vu des cas où l’extension “inactive” possédait encore des fichiers infiltrés, ou où un plugin inactif servait de dépôt à une charge utile, déclenchée plus tard via une dépendance activée.
Je commence donc par relever:

- toutes les extensions installées, leur statut (activée ou non), les versions, les dates de modification si vous y avez accès (via votre gestionnaire de fichiers ou un client SFTP), les fichiers présents dans leurs dossiers.
Le détail qui change tout, ce sont les dépendances. Certaines extensions chargent dynamiquement des fichiers à partir d’un autre dossier, ou incluent un script qui n’est pas visible tant que la fonctionnalité n’est pas appelée. Donc, même si vous ne voyez pas de code “malicieux” en surface, une inclusion indirecte peut être en cause.
Vérifications à faire sur les extensions et leurs dépendances
Voici le type de contrôles que je fais presque systématiquement, avant de prendre des décisions irréversibles:
- repérer les extensions installées récemment, surtout celles dont la version est incohérente avec ce que vous auriez utilisé habituellement; inspecter les fichiers supplémentaires présents dans les dossiers de plugin (répertoires “non standards”, fichiers nommés de façon vague, ou scripts qui ne correspondent pas à la structure habituelle); rechercher dans chaque plugin des appels à des fonctions de chargement fichiers, comme eval, base64_decode, gzinflate, ou l’utilisation d’URL externes pour récupérer du code; vérifier les dépendances déclarées (fichiers principaux qui incluent d’autres bibliothèques, ou références à d’autres plugins via leurs chemins); contrôler les hooks WordPress utilisés par le plugin (fichiers qui accrochent init, wp_enqueue_scripts, template_redirect, ou qui modifient le contenu de pages).
Cette inspection peut se faire avec un éditeur de texte, en local, ou directement via l’accès fichiers. J’évite de me baser uniquement sur “ça ressemble à du code bizarre”. Je préfère recouper: code d’inclusion, présence de mécanismes de chargement dynamique, et lien avec des symptômes observés.
La partie la plus piégeuse: les dépendances invisibles
Quand on parle de dépendances, il y a deux familles.
La première, c’est la dépendance “normale” au sens WordPress: une extension qui inclut un autre module parce qu’elle l’utilise. Ça peut être parfaitement propre.
La seconde, c’est la dépendance “d’attaque”, celle qui n’a pas de raison métier. Un plugin peut embarquer un composant en dur, masquer sa logique, ou utiliser un nom de bibliothèque générique, pour se faire passer pour un package légitime. Dans certains incidents, le code malveillant n’est pas dans le fichier principal de l’extension, il est dans un dossier “vendor”, “lib”, ou dans un fichier chargé conditionnellement.
J’ai vu un cas où l’extension semblait inoffensive dans son fichier principal, mais une dépendance localisée dans un sous-dossier contenait une logique d’envoi de données et une altération du rendu côté front. La suppression immédiate de l’extension avait amélioré la situation, mais pas complètement, car une autre extension chargée continuait à inclure la dépendance (chemin statique partagé, ou inclusion via un hook commun).
Le piège classique, c’est le raisonnement “si je retire A, alors B ne peut plus s’exécuter”. C’est vrai si B n’est invoqué que par A. Si B est aussi appelé par une autre extension, un thème, ou un fragment persisté, l’infection peut continuer.
Méthode pragmatique de vérification: isoler sans casser
Pendant un nettoyage, vous devez garder le contrôle. L’objectif est de confirmer l’implication d’une extension et de sa dépendance, sans créer une nouvelle panne.
Le plus sûr, c’est de travailler en environnement de staging si vous en avez un, sinon en branchant une fenêtre de maintenance et en faisant des tests rapides en local ou via un clone.
Un scénario que j’utilise souvent consiste à:

Ce processus devient très efficace quand vous ciblez les extensions “récemment modifiées” ou celles dont le code contient des mécanismes de chargement dynamique. Si la désactivation supprime le problème, vous gagnez une preuve. Si le problème persiste, vous élargissez aux dépendances, aux thèmes, ou à une persistance via la base de données.
Signaux qui orientent vers une compromission via extensions
Il y a des signaux assez concrets, sans avoir besoin de transformer votre diagnostic en enquête policière. Sur plusieurs incidents, ces indices reviennent.
- présence d’URL externes injectées ou appelées au moment de l’affichage, même si elles ne sont pas documentées par le plugin; modifications répétées de fichiers de plugin ou de dépendances, alors que vous ne les avez pas touchés; apparitions de scripts ou de fichiers ajoutés “à côté” d’une extension, par exemple des bundles avec des noms non descriptifs; comportements déclenchés par des actions WP précises (publication, changement de page, passage dans une zone d’administration); alertes dans les logs PHP, même basiques, qui mentionnent des inclusions de fichiers inattendues.
Ces signaux ne prouveront pas à eux seuls que c’est un virus. Mais ils rendent l’hypothèse très plausible, et surtout ils orientent vers la bonne zone d’inspection.
Pourquoi la version des extensions compte, même quand on cherche du code
Beaucoup de nettoyages se focalisent sur “trouver le fichier malveillant”. Pourtant, la version d’une extension apporte un contexte indispensable. Un plugin peut être compromis via une vulnérabilité connue, ou via une intégration de dépendances externes (comme une bibliothèque JS) qui n’est plus maintenue.

Je n’appuie pas tout mon diagnostic sur “cette version est ancienne, donc c’est forcément l’attaque”. Ce serait trop simpliste. En revanche, si vous trouvez une extension très ancienne, combinée à des modifications de fichiers et à des URLs externes injectées, vous avez un faisceau d’indices.
Le bon réflexe est aussi de vérifier les mises à jour disponibles, mais après avoir sécurisé. Une mise à jour “à chaud” peut réparer une vulnérabilité, mais elle peut aussi masquer ce que vous auriez pu analyser. En incident response, je préfère d’abord comprendre, ensuite corriger.
Étapes de correction: analyser, sauvegarder, puis nettoyer de manière cohérente
Une fois que vous avez identifié une extension à risque, le nettoyage ne doit pas être une simple suppression “au hasard”. Il doit être cohérent avec la persistance possible.
Le schéma que j’ai le plus vu fonctionner est:
- conserver une copie des fichiers et du dossier plugin avant tout retrait si vous n’en avez pas encore; vérifier si la base de données contient des options anormales liées à ce plugin (par exemple des options qui stockent du code ou des configurations); supprimer ou remplacer l’extension par une version propre, provenant du dépôt officiel ou du fournisseur, pas d’un “repack” trouvé ailleurs; inspecter les dépendances associées, car il arrive que le code suspect soit dans un composant partagé.
Dans certains cas, la meilleure approche n’est pas “réinstaller un plugin”. C’est de retirer définitivement le plugin, puis de reconstruire la fonctionnalité manquante. C’est particulièrement vrai si le plugin est peu maintenu, ou s’il n’a pas de besoin clair dans votre architecture.
Cas pratique: l’extension “OK” mais la dépendance “pas OK”
Un exemple concret, sans entrer dans des détails sensibles.
Dans un site e-commerce, les symptômes étaient une altération du front sur certaines pages produits, avec injection de scripts côté page. L’extension la plus suspecte, à première vue, était celle qui gérait la mise en page et certaines options. Pourtant, après inspection rapide, le fichier principal semblait normal.
Ce qui a changé la donne, c’est l’analyse des dépendances. Dans un sous-dossier de cette extension, on trouvait un fichier qui n’apparaissait pas dans la distribution attendue, et surtout un mécanisme d’inclusion conditionnelle. En regardant la logique, le fichier externe était chargé uniquement dans certains contextes, ce qui expliquait le caractère intermittent des symptômes.
Après désactivation de l’extension, le problème revenait parfois, car une autre extension, celle qui gère des assets, utilisait les mêmes hooks. On a fini par:
- isoler l’extension par étape, remplacer le dossier complet de la première extension par une copie propre, et désactiver l’autre extension le temps d’ôter toute trace.
Le point clé, c’est que l’“extension visuellement suspecte” n’était pas la vraie source, la dépendance l’était.
Remplacer proprement, sans rester dans l’incertain
Quand vous concluez qu’une extension est en cause, vous avez souvent deux options: suppression et réinstallation propre, ou suppression et remplacement par une alternative.
Le remplacement “propre” implique une discipline:
- récupérer le package depuis une source fiable, vérifier que les fichiers après déploiement ne contiennent pas les artefacts suspects, contrôler que le plugin ne réintroduit pas de comportement (tests sur quelques pages cibles).
Ce contrôle par tests est indispensable. J’ai déjà vu des cas où une extension réinstallée semblait propre au moment de l’analyse statique, mais reprenait un comportement à cause d’options persistées en base. Par exemple, certaines options peuvent stocker du contenu injecté, ou configurer des URLs externes. Dans ces situations, il ne suffit pas de remplacer les fichiers. Il faut aussi nettoyer la configuration anormale.
Dépendances partagées: quand la même librairie circule entre plusieurs plugins
Les dépendances partagées compliquent tout. Vous pouvez avoir une bibliothèque JS ou une logique PHP qui se retrouve dans plusieurs extensions, soit parce qu’elles la copient, soit parce qu’elles la référencent dans des chemins similaires.
Quand l’infection touche une dépendance partagée, deux effets apparaissent souvent:
- les symptômes peuvent rester même si vous supprimez une extension, parce que la dépendance est encore appelée ailleurs; les signatures de code ne se concentrent pas sur un seul plugin, elles se répartissent dans plusieurs dossiers.
C’est pour ça que, lors d’un nettoyage, je préfère faire une recherche globale de patterns, plutôt que de regarder uniquement le plugin suspect. La recherche peut porter sur des chaînes d’URL, des noms de fichiers ajoutés, des fonctions d’inclusion ou des marqueurs spécifiques. Le bon niveau de détail dépend de ce que vous avez le droit de faire sur votre serveur, et du temps disponible.
Après le nettoyage: sécuriser le futur en traitant les dépendances comme des dépendances
Nettoyer une infection, c’est une chose. Empêcher le retour, c’en est une autre. Les extensions et leurs dépendances, encore une fois, sont au centre.
Les mesures qui font vraiment la différence sur le long terme ne sont pas forcément “spectaculaires”. Elles sont souvent simples:
- limiter les extensions au strict nécessaire, mettre à jour régulièrement les extensions de façon contrôlée, supprimer les plugins inutilisés, y compris ceux qui ne sont pas activés, surveiller les fichiers modifiés dans wp-content/plugins/ et détecter les ajouts, renforcer l’accès admin et vérifier les comptes.
Je sais que tout ça peut sembler évident, mais dans les incidents concrets, c’est rarement un seul gros geste qui manque. C’est souvent un ensemble de petits angles morts: un plugin installé pour un besoin ponctuel, puis oublié, ou une dépendance qui n’est jamais mise à jour parce que personne ne sait qu’elle existe.
Une discipline de jugement: quand garder et quand jeter
Il y a un dilemme que j’ai toujours trouvé inconfortable: faut-il analyser longtemps une extension avant de la supprimer?
Si vous avez un environnement stable, beaucoup de logs, et du temps, analyser en profondeur est utile. Mais si le site est fortement perturbé, si des injections apparaissent en front, et si les visiteurs voient du contenu anormal, vous devez agir vite et avec méthode. Dans ce cas, la stratégie de “préserver une preuve, puis remplacer” est souvent la plus saine.
J’ai pris l’habitude de ce compromis:
- préserver ce qui peut servir (une copie avant action, une capture de l’état des fichiers concernés, un export des options si nécessaire), puis effectuer des changements qui réduisent le risque le plus vite possible (suppression ou remplacement d’extensions, nettoyage base de données si besoin).
Ce n’est pas une question de courage, c’est une question de gestion du risque.
Vérifier les dépendances ne veut pas dire tout casser
Un dernier point important: vérifier les dépendances ne doit pas transformer votre nettoyage en démolition. WordPress est un écosystème. Certaines extensions dépendent d’autres, et certaines dépendances sont légitimes.
Votre meilleur allié, c’est la corrélation. Si vous voyez un symptôme, cherchez le chemin d’exécution probable, puis vérifiez les dépendances qui peuvent alimenter ce chemin.
Quand vous désactivez une extension, le changement de comportement doit être lisible. Si vous ne voyez rien, ce n’est pas forcément un échec, cela peut indiquer soit une autre extension, soit une dépendance partagée, soit une persistance ailleurs (base de données, thème, tâches planifiées, ou chargement de fichiers).
En pratique, le bon déroulé consiste à avancer par hypothèses, pas par certitudes. Et à chaque étape, vous exigez une observation: une page, une ressource, un log. Pas juste un “ça a l’air normal”.
Si vous voulez, je peux aussi proposer une https://gardewp.fr/nettoyage-malware-wordpress/ grille de diagnostic orientée “symptômes” (injection front, redirections, comportements admin, erreurs serveur) pour choisir plus vite quelles extensions et dépendances inspecter en premier, sans multiplier les manipulations.