WordPress infecté : loguer les événements et analyser les traces

Quand un site WordPress est compromis, la première tentation consiste à “nettoyer” vite fait, remplacer quelques fichiers, puis republier. Le problème, c’est que les actions rapides effacent souvent les preuves. Or, pour restaurer proprement, réduire le risque de récidive, et comprendre comment l’attaque a réussi, il faut loguer les événements et analyser les traces avec méthode.

Dans cet article, je parle de ce que j’ai vu le plus souvent sur des environnements WordPress réels: attaques par plugin ou thème, comptes créés en douce, webshells déposés via un thème modifié, injections qui ne touchent pas seulement les pages visibles, mais aussi le navigateur et le navigateur de l’admin via des chargements côté client. Le fil conducteur reste le même: collecter, corréler, puis décider.

Le but n’est pas de produire une “enquête” au sens judiciaire. C’est de récupérer une vérité opérationnelle, assez solide pour: stopper ce qui persiste, identifier la porte d’entrée, et remettre le site dans un état maîtrisé.

Ce que vous devez chercher avant de “nettoyer”

Un site WordPress infecté n’est pas seulement “un contenu malveillant affiché”. L’infection peut laisser des traces dans plusieurs couches:

    le serveur web (requêtes inhabituelles, téléchargements, accès à des endpoints suspects), le système de fichiers (modifications, créations, permissions anormales), la base de données (utilisateurs créés, options modifiées, cron altéré), WordPress lui-même (fichiers dans wp-content, plugins ou thèmes modifiés, hooks ajoutés), parfois le comportement client (scripts injectés, redirections, chargements externes au moment du rendu).

Si vous nettoyez sans regarder ces couches dans l’ordre, vous risquez de rater la cause. Et la récidive devient très probable, notamment lorsque l’accès initial n’a pas été corrigé.

Ce que je recommande, dans le temps court, c’est de figer la situation autant que possible. “Figer” ne veut pas dire “éteindre tout” dans tous les cas, mais limiter les modifications tout en collectant.

Figurer la scène: réduire les dégâts tout en collectant

La collecte de traces a un coût: CPU, espace disque, temps humain. Mais quand un site a déjà été compromis, vous payez plus cher si vous perdez l’historique.

Avant de changer quoi que ce soit, j’évalue trois contraintes simples:

La facilité de sauvegarde et la capacité à stocker des artefacts (logs, exports base, copies de fichiers), Le niveau de risque lié à l’exposition (site public, formulaire d’authentification, pages indexées), La possibilité de mettre en quarantaine sans casser l’activité (maintenance, blocage d’IP, durcissement temporaire).

Sur beaucoup d’hébergements, les logs système tournent sur une rotation courte. Si vous n’en faites rien tout de suite, vous ne les récupérerez plus. Sur d’autres, vous avez plusieurs jours, parfois plusieurs semaines, mais avec des granularités variables. Le bon réflexe est donc de prioriser: exporter les logs pertinents et préparer des copies chiffrées ou au minimum vérifiées.

Quoi loguer exactement, et à quel niveau

Pour analyser des traces WordPress, j’aime raisonner en “couches”, parce que les attaques touchent rarement une seule couche. L’objectif est de pouvoir relier une action à une cause.

Logs côté web server (les plus immédiats)

Ce sont souvent les premiers à raconter l’histoire. Les signaux fréquents: pics de requêtes sur des chemins inattendus, tentatives sur des fichiers PHP dans des répertoires non utilisés, téléchargement de charges, paramètres aux valeurs étranges.

Selon votre stack, il faudra viser au moins:

    les accès HTTP (code retour, user-agent, IP source, chemins), les erreurs (erreurs PHP, accès refusés, timeouts), éventuellement les logs du reverse proxy ou du load balancer si vous en avez un.

Même si WordPress est “le problème”, l’attaque se voit souvent comme un trafic web hors norme.

Traces WordPress et applicatives

WordPress ne logue pas tout par défaut. Il faut donc vérifier ce qui est activé. L’erreur log applicatif, quand il est disponible, peut contenir des indices: inclusions de fichiers, warnings lors de l’exécution de code injecté, tentatives d’accès à des endpoints.

Il est aussi utile de collecter ce que WordPress considère comme événements: modifications de plugins, changements d’options, création d’utilisateurs. Mais attention: en cas d’infection, certains développeurs malveillants désactivent ou contournent des mécanismes internes, donc ne partez jamais du principe que l’absence de log implique l’absence d’activité.

Logs système et événements OS

Sur un serveur Linux, les traces OS peuvent aider à identifier une action “mécanique”: exécution de commandes inattendues, écritures de fichiers, activité du cron, connexions SSH, accès FTP.

Il ne faut pas s’attendre à tout avoir, selon l’hébergement. Dans un shared hosting, vous aurez moins de visibilité. Dans un VPS ou un serveur dédié, vous pouvez exploiter davantage.

Historiques de base de données

La base de données n’est pas seulement “une cible”, elle est aussi un témoin. Les infections persistent souvent via des options modifiées, des configurations de cron, des tables liées aux formulaires, ou des utilisateurs créés.

Le meilleur levier consiste à exporter la base dans un état connu et à corréler ensuite avec les logs. Si vous n’exportez pas, vous vous limitez à l’observation actuelle, ce qui perd de l’information sur le “avant”.

Une collecte courte et utile (sans tout casser)

Quand je fais une première collecte, je cherche un équilibre entre exhaustivité et temps. L’idée est de capturer ce qui permet une analyse rapide, puis de prolonger si nécessaire.

Voici une collecte initiale, volontairement pragmatique:

Exporter les logs HTTP et erreurs des dernières 24 à 72 heures, ou plus si la rotation le permet Récupérer une copie vérifiée de wp-content et des fichiers PHP au niveau racine (en privilégiant l’intégrité, par exemple via sommes de contrôle) Exporter la base de données (au minimum les tables liées aux utilisateurs, aux options, et à wp-cron) Conserver la configuration web actuelle (Nginx ou Apache, et configuration PHP-FPM si applicable) Lister l’état courant des plugins et thèmes, avec leurs versions et dates d’installation si elles apparaissent dans l’admin

Cette liste ne remplace pas une investigation complète, mais elle donne souvent assez pour comprendre les trajectoires.

Lecture des traces web: trouver les “chemins” qui ne devraient pas exister

Une attaque laisse rarement une empreinte uniforme. Elle laisse plutôt des comportements répétables: même patterns d’URL, même séquences de paramètres, mêmes codes retour.

Sur un site infecté, je m’attends à voir au moins un de ces scénarios:

    tentatives de chargement de scripts dans des répertoires non exposés, accès à des endpoints WordPress qui ne sont pas utilisés par des navigateurs normaux, appels à des fichiers temporaires ou à des chemins “cachés” (par exemple via des noms plausibles), user-agent anormalement générique, ou variations rapides sur des user-agent connus.

Le point clé est la corrélation. Si vous repérez un endpoint suspect dans les logs web, il faut chercher s’il existe dans le système de fichiers. Si vous repérez un écart dans les options, il faut vérifier si les requêtes autour de cette période coïncident.

Côté codes retour, ne vous fiez pas uniquement aux 200. Une charge peut être testée, échouée, puis retentée. Dans ces cas, les codes 404 et 403 peuvent être aussi révélateurs que les réponses “réussies”.

Traces WordPress: versions, modifications, et “qui a touché quoi”

WordPress offre des indices, mais ils sont incomplets dans les cas d’infection. Les attaques réussies passent souvent par l’interface d’administration, ou par des mécanismes qui écrivent directement sur le système.

Je traite trois catégories d’indices WordPress avec une logique de preuve:

1) Plugins et thèmes qui ont changé

Un plugin ou un thème modifié sans mise à jour officielle est un drapeau. Sur certains hébergements, vous pouvez voir des dates de modification de fichiers. Sur d’autres, vous avez besoin de comparer un état actuel à un état connu (sauvegarde propre, image de déploiement, ou contrôle d’intégrité basé sur sommes de contrôle).

Dans mes investigations, les modifications “propres” arrivent avec un pattern: mise à jour, puis des changements cohérents sur plusieurs fichiers, y compris la version. Les modifications malveillantes tendent à être ciblées: ajout d’un petit bloc à un fichier qui a l’air normal, ou ajout d’un nouveau fichier PHP dans wp-content.

2) Utilisateurs, rôles, et création de comptes

Beaucoup d’infections gardent une porte ouverte en créant un compte administrateur. Ce qui rend la détection difficile, c’est que le compte peut exister depuis quelques jours ou semaines, et que l’attaquant ne s’en sert pas forcément tous les jours.

Sur un site WordPress infecté, je vérifie toujours:

    les comptes admin et éditeurs, les dates de création si accessibles, la dernière activité, les tentatives de connexion via logs serveur si possible.

Quand vous trouvez un compte louche, ne supprimez pas immédiatement sans conserver les traces. Parfois, l’attaquant déclenche des actions au moment où vous “nettoyez”, ce qui complique la corrélation.

3) wp-cron, options, et redirections

Les persistance se voient souvent dans wp-cron ou dans des options qui pilotent des comportements. Un cron mal configuré peut déclencher du code périodique, par exemple une tâche qui réinjecte du contenu ou qui exfiltre.

Les redirections et injections se manifestent aussi parfois via une logique conditionnelle: code exécuté uniquement pour certains user-agent, ou seulement sur les pages publiques, ou seulement pour l’admin.

Analyser les fichiers suspects: méthode d’attaque, pas méthode de stress

Quand vous ouvrez un fichier suspect, la question n’est pas “est-ce mal écrit ?”. La vraie question est “pourquoi ce fichier existe et comment il se connecte à WordPress”.

Ce que je cherche:

    des fonctions enveloppantes qui incluent d’autres fichiers à partir de chemins calculés, des mécanismes de détection (IP, headers, cookies) qui déclenchent le payload uniquement dans certains cas, l’usage discret de fonctions d’exécution ou de lecture de fichiers, des chaînes encodées ou des fragments qui paraissent inutiles dans le contexte, des hooks WordPress ajoutés de manière atypique (fichiers hors du plugin, injection via include, etc.).

Une bonne habitude: travailler en local sur une copie, pas sur le site en production. En cas de doute, vous pouvez annoter et comparer ligne à ligne avec des sources “propres” que vous avez le droit de conserver (par exemple la version distribuée du plugin ou une sauvegarde saine). Je privilégie la comparaison binaire et logique: même si vous identifiez un bloc malveillant, la compréhension de l’intégration aide à trouver l’origine.

Corrélation: relier une requête à une modification

La partie la plus utile de l’analyse, c’est la corrélation temporelle.

Un bon exercice consiste à construire une chronologie simple:

    période A: trafic web anormal, période B: modification de fichiers ou création d’un utilisateur, période C: apparition d’une injection visible ou de redirections.

Même si vous n’avez pas la seconde exacte, vous cherchez une cohérence. Si un fichier PHP a été modifié à la même heure que des requêtes suspectes, vous avez une piste concrète.

Dans certains cas, la corrélation vous montre que la “cause” est ailleurs que la “symptôme”. Par exemple, vous voyez une page injectée, mais les requêtes d’injection montrent plutôt une phase de chargement de code suivie d’une persistance qui passe par la base de données. Dans ces situations, supprimer la page injectée ne suffit pas, et vous devez neutraliser le mécanisme de persistance.

Exemple de persistance fréquente (et comment la repérer)

Sans prétendre à l’exhaustivité, les persistance sur WordPress ont souvent des points communs:

    un fichier de charge placé dans un répertoire accessible, un code qui se déclenche via un hook WordPress, une option ou un cron qui recharge la charge à intervalle, un utilisateur administrateur qui peut réinjecter ultérieurement.

En pratique, je regarde deux choses en priorité:

    le “où” le code se trouve, dans wp-content et au voisinage de mécanismes WordPress, le “quand” il s’exécute, via des conditions dans le code ou via une planification.

Quand vous combinez ça avec les logs web, vous pouvez souvent déterminer si l’attaque est:

gardewp.fr
    opportuniste (sur un pic de trafic ou une tentative ciblée), persistante (répétée à intervalles), interactive (l’attaquant s’appuie sur l’admin pour piloter).

Pièges courants pendant l’analyse

Il y a quelques erreurs qui reviennent, parce qu’elles sont “logiques” quand on est stressé, mais coûteuses ensuite.

1) Se contenter du site visible

Une infection peut modifier l’admin seulement, ou injecter un script uniquement pour certains navigateurs. Si vous testez uniquement sur votre ordinateur, vous pouvez rater le comportement réel.

2) Nettoyer avant de sauvegarder l’avant

Sans sauvegarde et sans copie des fichiers, vous perdez l’instantané. Ensuite, vous ne savez plus ce qui a changé et quand.

3) Supposer que “les logs suffisent”

Certains hébergeurs limitent les logs. Certains compromis désactivent des pistes applicatives. Vous devez donc croiser.

4) S’attaquer uniquement aux fichiers

Si la persistance est dans la base, vous nettoyez des fichiers et l’infection revient.

5) Revenir à l’état “propre” sans corriger la porte d’entrée

Si une faille de plugin ou un accès faible persiste, le compromis se reproduit. L’analyse doit déboucher sur une correction, pas seulement un retrait de code.

image

Décider quoi faire ensuite: quarantaine, restauration, durcissement

Une fois que vous avez des traces suffisantes, vous devez choisir une stratégie. Elle dépend de votre niveau de preuve, de la criticité du site, et de votre capacité à restaurer.

Trois trajectoires typiques:

    mise en quarantaine rapide si le site diffuse du contenu malveillant ou si vous suspectez une exfiltration active, restauration depuis une sauvegarde saine si vous avez un point de retour fiable, réparation par neutralisation ciblée si vous avez une petite zone compromise et si le reste est cohérent avec un état connu.

Dans tous les cas, la correction de la porte d’entrée est obligatoire. Souvent, cette porte d’entrée n’est pas le “payload”. C’est:

    un plugin obsolète, un thème modifié, une configuration d’accès trop permissive, une faiblesse sur l’authentification, ou une surface d’upload exploitable.

Durcissement après analyse: éviter la récidive sans tout casser

Le durcissement n’a de valeur que s’il est adapté à votre environnement. Une mesure “standard” peut casser un plugin légitime, ou empêcher votre équipe de déployer.

Ce que je considère comme priorités réalistes après une investigation sur un WordPress compromis:

    réduire la surface de plugins et thèmes actifs, vérifier les rôles et nettoyer les comptes douteux, mettre à jour ce qui doit l’être, sans réintroduire de composants modifiés, renforcer l’authentification admin et limiter l’accès si possible, corriger les permissions et l’exécution là où c’est pertinent, surveiller avec des alertes adaptées, pas seulement “consigner”.

Le point délicat, c’est que certains durcissements doivent être appliqués avec attention, car WordPress est flexible et beaucoup de sites utilisent des plugins qui exigent des règles spécifiques.

Signaux d’alerte à surveiller dans vos traces

Même après restauration, je conseille de garder un œil sur quelques motifs, parce qu’ils reviennent dans beaucoup de compromissions.

Voici les signaux que je cherche en premier, car ils donnent souvent une lecture rapide:

Pics de requêtes vers des fichiers ou chemins inhabituels, surtout en dehors des heures “normales” Codes 404 et 403 répétés sur des URL qui ressemblent à des tests de payload Création ou modification de comptes administrateurs, ou activité d’un compte nouvellement créé Changements dans wp-content ou ajout de fichiers PHP dans des emplacements non attendus Déclenchements récurrents d’actions planifiées, cohérents avec un cron modifié ou des hooks persistants

Ce ne sont pas des preuves à eux seuls. Mais ce sont des indicateurs qui justifient une vérification ciblée.

Mettre en place une routine de logging et d’analyse plus légère, mais durable

Une investigation ponctuelle aide, mais l’idéal est d’éviter que “l’urgence” devienne votre mode de fonctionnement.

Sans tomber dans l’excès, vous pouvez instaurer une routine qui combine logs, intégrité, et vigilance sur les changements. L’objectif est de réduire le temps entre “ça commence” et “on sait quoi faire”.

En pratique, cela veut dire:

    garder une politique de rétention cohérente pour les logs critiques, surveiller les changements de fichiers dans wp-content et dans les fichiers PHP exposés, suivre les événements WordPress qui indiquent un changement d’état, établir une base de référence avant de prendre le moindre risque.

Le piège, c’est d’activer une surveillance si lourde qu’elle finit par être ignorée, parce que trop d’alertes sont bruitées. Je préfère des alertes orientées “changements” et “patterns”, plutôt que des alertes brutes sur chaque requête.

Cas particulier: quand vous n’avez pas assez de logs

Sur certains hébergements, vous aurez des logs incomplets, pas de détail utile, et des rotations trop courtes. Dans ce cas, l’analyse se déplace vers:

    la comparaison des fichiers actuels à un état connu (sauvegarde saine), l’analyse des persistance dans la base de données, et la vérification des comptes utilisateurs et des mécanismes d’exécution.

Le manque de logs ralentit, mais il ne bloque pas forcément. Vous perdez surtout la capacité à “prouver” la chronologie fine. Vous pouvez quand même reconstruire un scénario plausible, à partir des différences.

Vérifier la restauration: preuve par l’absence, et pas seulement par le “ça marche”

Quand vous restaurez ou remplacez, le risque est de vérifier uniquement l’affichage des pages. Or, une infection peut rester active sans se manifester dans le test manuel.

Après restauration, je recommande d’appliquer une validation à plusieurs niveaux:

    tester l’interface publique et l’admin dans des contextes différents (navigation normale, cookies admin, user-agent), vérifier les changements de fichiers et leur cohérence avec l’état attendu, vérifier les utilisateurs, les options et la planification, et, si c’est possible, faire tourner des requêtes d’essai contrôlées sur les endpoints suspectés.

Cette validation demande du temps, mais elle réduit les retours en arrière.

Restaurer proprement, puis apprendre: ce que l’analyse doit produire

L’analyse de traces n’est pas seulement une question de curiosité. Elle doit aboutir à des décisions claires. En général, elle doit vous permettre de répondre:

    quelles composantes ont été modifiées (plugins, thèmes, fichiers racine, répertoires), où la persistance se loge (base, cron, hooks), quel était le vecteur probable (faille, mot de passe, upload, mauvaise configuration), ce qui doit être changé durablement (mises à jour, permissions, durcissement, surveillance).

Le “site WordPress infecté” n’est plus une situation abstraite une fois que vous pouvez expliquer, même avec une marge d’incertitude, comment ça a pris. Cette explication guide la correction.

Si vous voulez, décrivez votre contexte (hébergement, reverse proxy ou non, accès aux logs, et si vous avez une sauvegarde antérieure). Je peux vous proposer une stratégie de collecte et d’analyse adaptée, sans liste de tâches interminable, et avec un ordre de priorité réaliste pour votre niveau de visibilité.