Quand un WordPress se “met à faire n’importe quoi”, on pense souvent au pire très vite. Une page qui redirige. Un bloc de texte en bas qui n’a rien à faire là. Des emails qui partent depuis le compte admin, même si vous n’avez rien fait. Ou encore un site qui devient lent, puis impossible à charger, parce que quelqu’un a transformé votre hébergement en relais pour de la fraude.
Le réflexe est de “tout nettoyer”, puis de “réinstaller”. Parfois, c’est nécessaire. Mais le vrai gain vient d’un travail plus patient: retrouver le fichier source du malware et comprendre comment il s’est installé, pour que le nettoyage ne soit pas un simple pansement. Sur un WordPress infecté, localiser la première trace utile peut changer le résultat en profondeur, notamment quand la compromission n’est pas limitée à un seul fichier.
Ce texte vous guide dans une démarche pratico-pratique pour remonter à la source: repérer les anomalies, identifier le mécanisme d’infection, puis confirmer le fichier coupable. On va aussi parler des cas où le “fichier source” n’est pas un seul fichier PHP évident, parce que les attaques modernes n’en ont pas toujours besoin.
Comprendre ce que vous cherchez vraiment
Le mot “malware” fait penser à un fichier unique. Dans les faits, sur WordPress, on rencontre souvent un couple inséparable:
- un point d’entrée (souvent une modification de fichier, une porte dérobée, ou un plugin détourné), puis une routine qui persiste (backdoor, cron malicieux, chargement dynamique depuis une URL, ou injection via base de données).
Quand vous cherchez “le fichier source”, vous cherchez en réalité le premier composant qui permet à l’attaque de s’exécuter à chaque chargement, ou périodiquement (par exemple via WP-Cron). Le “fichier qui affiche le contenu” n’est pas toujours la cause. Il peut être une conséquence d’une étape précédente, et le vrai responsable se cache ailleurs.
Sur le terrain, je vois deux scénarios qui reviennent souvent:
1) Infection par modification de thème ou de plugin
Le code malveillant s’ajoute dans des fichiers du thème (functions.php, footer.php) ou dans un plugin, parfois avec une apparence normale. Vous trouvez un eval, un base64_decode, un appel à gzinflate, ou un code qui manipule $_POST et $_GET d’une façon qui n’a aucune raison d’exister.2) Infection par persistance côté base de données
Le code n’est pas forcément dans un fichier. Parfois, l’attaque se contente d’injecter un contenu dans les options WordPress, les posts en brouillon ou des champs liés à des plugins. Le fichier “source” peut alors être plus difficile à isoler, car la logique peut résider dans la base, puis s’actualiser selon des conditions.Dans les deux cas, votre objectif est de faire remonter l’origine jusqu’à un composant traçable. Le tri se fait avec des preuves, pas avec des suppositions.
Première observation: ce que l’attaque fait, pas juste ce qu’elle change
Avant d’ouvrir l’arborescence des fichiers, observez le comportement. Les détails comptent.
Si vous voyez des redirections systématiques vers une URL douteuse, regardez si elles se produisent:
- uniquement sur certaines pages, seulement quand un paramètre est présent dans l’URL, uniquement pour certains user agents (navigateurs, bots), uniquement après un certain nombre de minutes (cron et tâches planifiées), ou après une action précise (connexion, envoi de formulaire, ajout d’un plugin).
Sur WordPress, beaucoup de backdoors sont déclenchées de manière “discrète”. Un script peut n’activer la charge utile que si une variable est fournie. Par exemple, la présence d’un paramètre id= ou d’un header spécifique dans la requête. Si vous ne reproduisez pas le déclenchement, vous risquez d’inspecter le mauvais fichier.
Un petit test simple, sans être intrusif: faites deux captures de comportement, l’une avant connexion, l’autre après connexion. Si la modification n’apparaît que pour les utilisateurs connectés, cela pointe vers une injection liée à un contexte (template, hooks, rôles, options chargées).
Verrouiller avant d’inspecter (sinon vous perdez les preuves)
Quand un site est compromis, le premier risque est d’aggraver la situation. Le second est de détruire vos indices.
Si l’hébergement permet des charges lourdes, un malware peut continuer à recruter des ressources, envoyer du spam, ou attaquer d’autres cibles. Et pendant ce temps, les logs se remplissent, les fichiers peuvent changer, et l’attaque peut “s’auto-réparer” en fonction de votre nettoyage.
Une approche souvent raisonnable consiste à isoler le site le temps de l’analyse:
- mettez votre site en mode maintenance, désactivez temporairement l’accès public si votre contrôle d’hébergement le permet, gardez une copie des fichiers et de la base avant toute modification, figez l’état quand c’est possible.
Le compromis est réel: si vous coupez tout, vous perdez certains logs récents. Mais si vous laissez l’attaque agir, vous perdez aussi des repères. L’idéal est de sauvegarder rapidement, puis d’enquêter en limitant le risque.
Les indices les plus utiles dans WordPress
Le “fichier source” laisse rarement une empreinte unique. Vous cherchez une chaîne cohérente d’indices: un fichier modifié, un hook qui déclenche du code, une option ou un champ injecté, une tâche cron ajoutée, des logs qui mentionnent un appel suspect.
1) Vérifiez la cohérence des fichiers modifiés
L’approche la plus efficace consiste à comparer avec une version saine attendue. Si vous avez un thème custom, son code peut varier, mais WordPress “core” et beaucoup de plugins ont une structure connue.
Concrètement, recherchez:
- des fichiers ajoutés récemment, des fichiers avec une taille anormale, des modifications récentes dans wp-content/themes, wp-content/plugins et parfois wp-includes, des fichiers PHP qui ressemblent à des fichiers “utilitaires”, mais qui ont un comportement de chargement ou d’exécution.
Le code malveillant est souvent “sale” mais pas toujours. Certains acteurs ajoutent de la mise en forme pour imiter un style. Ce qui les trahit, c’est la logique: décode base64, exécute du code contenu dans une variable, tente de charger quelque chose depuis l’extérieur, ou manipule des paramètres de requête.
2) Regardez les endroits où WordPress appelle le code
Le malware cherche un point de passage. Parmi les zones fréquentes:
- functions.php du thème actif (ou des thèmes secondaires), les fichiers de template comme footer.php ou header.php, les fichiers principaux d’un plugin, surtout s’ils n’ont pas une raison d’être modifiés, les hooks ajoutés via add_action ou add_filter, les filtres de rendu, qui permettent d’injecter du HTML ou des redirections sans alerter immédiatement.
Quand vous trouvez un morceau de code qui semble “hors sujet” du thème (par exemple un traitement de requête et une exécution dynamique), il y a de fortes chances que vous soyez au bon endroit.
3) Scrutez la base de données pour la persistance
Même si vous trouvez un fichier suspect, la compromission peut se maintenir via des options.
Les endroits à vérifier, avec prudence, sont les données qui:
- stockent des fragments injectés, configurent des plugins, modifient des paramètres d’exécution, ou déclenchent l’ajout de hooks.
Sans vous donner une liste trop précise, l’idée est de chercher des modifications récentes et des valeurs incohérentes pour votre site. Une option qui contient du PHP, par exemple, est un drapeau rouge.
Sur beaucoup d’attaques, la base contient soit une charge utile encodée, soit une instruction du type “quand tel hook est exécuté, insère ce contenu”. Ensuite, le fichier “source” peut n’apparaître que comme une passerelle.
Méthode d’enquête: remonter du symptôme au point d’entrée
Vous voulez un processus. L’objectif est de réduire l’espace de recherche et d’éviter de supprimer au hasard.
Voici une démarche efficace, basée sur des indices observables.
1) Faites une copie et isolez l’environnement
Avant tout changement, créez une copie des fichiers et exportez la base. Si vous avez accès à l’hébergement, prenez aussi une copie des logs web et PHP. Si vous ne savez pas où ils sont stockés, regardez au minimum:
- logs du serveur web (Apache, Nginx), logs PHP (si activés), logs applicatifs de votre hébergeur.
Ensuite, travaillez sur la copie. C’est souvent là que les erreurs évitent les pertes de preuves.
2) Cherchez le “code exécutable” plutôt que le “code présent”
Un fichier modifié ne suffit pas. Il faut détecter le mécanisme.
Quand j’inspecte, je me concentre sur les signatures de comportements plutôt que sur la forme. Par exemple:
- exécution dynamique (eval, assert, inclusion de contenu décodé, création de fonctions avec du code, chargement de ressources distantes (fichiers téléchargés, file_get_contents utilisé pour obtenir du code puis exécuté), contrôle basé sur des entrées de requête ($_GET, $_POST, cookies), modifications de variables superglobales qui changent le traitement.
Un détail utile: dans les infections, on voit souvent des blocs conditionnels. Le code peut rester “silencieux” la plupart du temps, puis s’activer quand la requête correspond à un format précis.
3) Vérifiez les hooks et l’ordre de chargement
Sur WordPress, un hook agit comme un robinet. Le code malveillant peut s’enregistrer dans WordPress, puis attendre le bon moment.
Inspectez les fichiers qui contiennent des add_action ou add_filter. Ce sont des points de départ pour remonter vers le moment où l’injection se produit.
Si le site injecte du contenu dans le front, cherchez un filtre qui touche le rendu. Si le site redirige, cherchez un template_redirect, init ou un action qui intervient très tôt. La logique exacte dépend du comportement.
4) Utilisez les logs pour valider vos hypothèses
Sans logs, vous inspectez à l’aveugle. Avec des logs, vous pouvez confirmer.
Regardez quels fichiers sont appelés lors d’une requête qui déclenche le problème. Selon l’infrastructure, cela peut être:
- des logs PHP avec les chemins de fichiers, des logs applicatifs, des entrées qui montrent un 404 ou une tentative d’accès à un fichier ajouté (par exemple un script “cache” loggé comme manquant).
Un point pratique: si vous ne pouvez pas voir de logs PHP détaillés, utilisez les logs du serveur web et traquez les requêtes vers des chemins inhabituels. Les attaques déposent parfois des fichiers à des noms “discrets” et déclenchent l’accès depuis un bot qui appelle cette ressource.
Les faux coupables et les pièges classiques
C’est tentant: vous trouvez un eval dans un fichier et vous concluez immédiatement. Parfois, c’est vrai. Mais parfois, vous tombez sur un morceau qui vient du thème, d’un plugin légitime, ou même d’un code de compatibilité.
Voici les pièges fréquents que j’ai vus en intervention:
- Code encodé mais inoffensif: certains optimiseurs et minificateurs stockent du code encodé pour réduire la taille. La différence, c’est la logique d’exécution et l’absence de déclencheur sur requête. Plugin obsolète, mais pas malveillant: un plugin peut être vulnérable, donc l’infection y passe, mais le code “bizarre” n’est pas forcément là. L’entrée peut avoir été ailleurs. Différence entre “modifié récemment” et “injecté”: si vous avez mis à jour un plugin ou changé un thème, des fichiers peuvent avoir des timestamps récents. Il faut relier l’anomalie au comportement. Multiples couches: un fichier peut ne contenir que l’installation d’un chargement (par exemple une fonction qui inclut un autre fichier). Le fichier “source” réel est parfois le second maillon.
Mon conseil de méthode: ne supprimez pas immédiatement. Confirmez en lisant le flux d’exécution, puis vérifiez si le comportement disparaît après correction ciblée dans un environnement de test.
Deux cas où le “fichier source” se dérobe
Cas 1: l’attaque vit en base de données
Le site peut afficher du code ou rediriger sans qu’un fichier PHP “évident” soit présent.
Vous voyez alors des signes comme:
- des contenus “injectés” dans les pages, des modifications d’options, de nouveaux utilisateurs ou des rôles incohérents.
Dans ce cas, votre “source” peut être une valeur persistante, ou un mécanisme qui reconstruit du code au moment où WordPress charge certaines parties. Le nettoyage doit alors être dirigé vers la base, et pas seulement vers wp-content.
Cas 2: l’attaque recharge le contenu depuis l’extérieur
Certaines infections déposent un petit script, https://gardewp.fr/nettoyage-malware-wordpress/ qui va ensuite récupérer un payload depuis une URL externe au moment du chargement ou du cron.
Dans ce schéma, le fichier “source” peut sembler presque trivial, et pourtant il déclenche un chargement dangereux. Le vrai malware est alors distant.
Ce que vous voulez faire dans l’analyse, c’est identifier:
- quelles URLs sont consultées, dans quel contexte elles sont appelées, et si l’URL est stable ou changeante.
Une fois que vous savez ça, vous pouvez bloquer ou neutraliser l’accès sortant et vérifier si l’injection s’arrête.
Comment isoler le fichier coupable avec des tests raisonnés
L’inspection manuelle est incontournable, mais elle peut être complétée par des tests.
L’idée n’est pas d’éteindre le site comme une brute, mais de créer des conditions qui réduisent les variables. Par exemple:
- tester en désactivant temporairement un plugin suspect dans la copie, basculer le thème sur un thème par défaut si vous avez un accès safe, désactiver temporairement les tâches planifiées (si possible), vérifier si le comportement persiste quand vous changez le contexte.
Sur un site vivant, attention: chaque test peut modifier l’état (cookies, sessions, logs). Sur une copie, l’impact est moindre.
Le point clé est de savoir quoi tester en premier. Dans mon expérience, on commence souvent par:

- le thème actif (surtout si vous avez récemment modifié le front), les plugins qui ont été mis à jour ou qui ont une fonction proche du comportement observé (SEO, redirection, formulaires), les zones où des hooks anormaux apparaissent.
Procédure pratique pour trouver le fichier source (sans vous noyer)
Voici une méthode condensée, conçue pour être réalisable même quand vous n’avez pas un outil sophistiqué sous la main.
https://gardewp.fr/ Faites une copie complète des fichiers et exportez la base. Notez la date et l’heure du moment où le site “montre” le problème. Inspectez les fichiers modifiés récemment dans wp-content/themes et wp-content/plugins, en privilégiant ceux qui contiennent des exécutions dynamiques, des chargements distants, ou des conditions basées sur des entrées de requête. Cherchez dans chaque candidat la trace d’un déclenchement, par exemple un hook init, un filtre de sortie, ou une logique liée à WP-Cron. Confirmez avec le comportement, sur une copie de travail: désactivez ou mettez en pause le candidat, puis testez la page qui révèle l’infection. Une fois le fichier identifié, regardez autour: y a-t-il un second fichier appelé, une option stockée dans la base, un cron ajouté, un utilisateur fraîchement créé lié au même moment.Cette démarche n’essaie pas de deviner. Elle essaie d’établir un lien entre une modification et un comportement.
Nettoyer un site WordPress infecté sans casser ce qui reste utile
Vous avez le fichier ou le mécanisme. Ensuite vient le nettoyage. Et là, il faut un peu de discipline.
Le point délicat est de ne pas “sur-nettoyer” et de casser une partie légitime de votre site. Si vous supprimez un fichier thème dont vous avez besoin, vous perdez des fonctionnalités, et vous risquez aussi de masquer une partie de l’infection.
Sur un WordPress infecté, une approche souvent fiable consiste à:
- restaurer les fichiers WordPress et plugins depuis une source de confiance (version exacte), réintégrer uniquement le code custom après vérification, et traiter la base de données avec une logique “liste blanche” (ce qui doit exister, ce qui a changé, ce qui est suspect).
C’est là que le terme “nettoyer site WordPress infecté” devient concret: ce n’est pas juste supprimer un fichier. C’est restaurer l’intégrité du code, puis valider que la persistance a disparu.
Cas d’école: un scénario typique de backdoor dans un thème
Imaginons un thème actif qui a un functions.php légèrement modifié. Le fichier contient du code encodé dans une chaîne, suivi d’une condition qui vérifie un paramètre en GET. Quand ce paramètre est présent, le code est décodé et exécuté.
Le symptôme côté navigateur peut être une redirection ou une injection de script. Le symptôme côté serveur peut aussi être des requêtes vers des endpoints bizarres, déclenchées par le bot.
Dans l’enquête, vous repérez le fichier modifié. Vous cherchez le déclencheur. Vous testez la page qui déclenche normalement l’infection, puis vous comparez le comportement en supprimant temporairement la section hookée (sur la copie).
Une fois confirmé, vous restaurez le thème à la version d’origine, vous réappliquez uniquement vos modifications légitimes (celles que vous connaissez vraiment), puis vous vérifiez la base et les options liées aux plugins.
Si vous ne vérifiez pas la base, vous pouvez garder une persistance cachée. Si vous ne restaurez pas les fichiers à l’identique, vous pouvez réintroduire une porte.
Cas d’école: infection via plugin, mais source ailleurs
Autre situation courante: le malware semble dans un plugin, car il y a des lignes suspectes. Vous supprimez le plugin, et le problème ralentit, mais ne disparaît pas totalement.
C’est le signe que le plugin a agi comme relais, ou qu’un autre élément (base, thème, cron) conserve le comportement.
Souvent, un plugin initial “récupère” une charge utile, puis installe une persistance ailleurs. Vous devez donc remonter le plus tôt possible, au point d’entrée, pas seulement au point d’affichage.
La validation passe par une règle simple: vous devez expliquer pourquoi le comportement a cessé. Si vous ne pouvez pas expliquer le lien, vous n’avez pas fini.
Ce que vous devez vérifier après le nettoyage
Trouver le fichier source et le retirer, c’est la moitié du travail. L’autre moitié consiste à empêcher la réinfection.
Même sans entrer dans des détails d’attaque, j’ai vu des réinfections qui viennent d’un contrôle d’accès laxiste (mots de passe faibles, absence de mise à jour). D’autres fois, c’est parce que la vulnérabilité d’origine n’a jamais été corrigée.
Après le nettoyage, vérifiez au minimum:
- que tous les utilisateurs ont des mots de passe solides et pas de comptes inconnus, que WordPress, thèmes et plugins sont à jour, que les fichiers sensibles ne reprennent pas les mêmes modifications, que les tâches planifiées n’ont pas été ajoutées, que le comportement suspect ne revient pas après un délai (certaines charges se réactivent).
Cette phase est frustrante, mais c’est elle qui transforme une “intervention” en “retour durable”.
Pour finir: comment savoir que vous avez réellement trouvé la source
Un bon indicateur est l’absence de persistance après plusieurs cycles.
Si vous avez juste désactivé un fichier suspect, mais que la base contient encore un déclencheur, le comportement peut revenir au prochain chargement d’une page ou au prochain cron. Si l’infection recharge depuis l’extérieur, elle peut aussi se réactiver une fois que les URL sont de nouveau accessibles.
Un autre indicateur est la cohérence des preuves. Vous avez un fichier modifié, un hook ou un déclencheur, et un comportement qui correspond. Quand vous neutralisez ce maillon, le comportement disparaît de manière reproductible.
Dans la plupart des cas, c’est ce trio qui valide votre diagnostic.
Si vous êtes bloqué: quand demander de l’aide
Parfois, l’analyse locale est trop lente, ou l’accès à la base et aux logs est incomplet. Dans ces cas, une aide externe peut être utile, à condition de transmettre les bons éléments:
- copie des fichiers et de la base (au moins l’export), logs disponibles, liste des symptômes observés et du moment précis où ils se produisent, chronologie des changements que vous avez faits (mises à jour, nouveaux plugins, modifications de thème).
L’aide technique pourra alors confirmer rapidement le fichier source et proposer un plan de correction durable.
Si vous me dites votre configuration (version de WordPress, plugins présents, symptôme exact: redirection, injection HTML, ralentissements, erreurs 500, comptes créés, présence de cron suspect), je peux vous proposer une stratégie d’enquête plus ciblée, toujours orientée vers la preuve et la recherche du vrai point d’entrée pour un nettoyage efficace du site WordPress infecté.