Désinfection WordPress : contrôler les logs serveur après incident

Quand on parle de désinfection WordPress, on pense souvent à “supprimer ce qu’il ne faut pas” puis à réinstaller proprement. C’est normal, parce que l’image mentale du piratage reste celle des fichiers corrompus ou des thèmes injectés. Pourtant, dans la vraie vie, la partie la plus révélatrice arrive après le nettoyage: contrôler les logs serveur pour vérifier ce qui s’est passé, comprendre comment l’attaquant a pris pied, et surtout éviter la récidive.

J’ai vu des sites “réparés” en apparence, avec une liste de fichiers nettoyée, une mise à jour du cœur WordPress, et pourtant une nouvelle vague d’injections 24 à 72 heures plus tard. Dans plusieurs cas, la cause n’était pas la présence d’un fichier malveillant évident, mais l’existence d’un chemin d’accès encore valide: identifiants réutilisés, rôle trop permissif, plugin abandonné mais accessible, ou script “dormant” qui déclenchait des actions à des moments précis. Les logs serveur sont ce qui permet de trancher.

Ce qui suit n’est pas une procédure magique valable pour tous les hébergements. C’est plutôt une façon de raisonner et de lire les traces avec le bon niveau de prudence, pour relier les événements entre eux: requêtes web, erreurs PHP, connexions réseau, événements d’authentification, et changements de fichiers.

image

Pourquoi les logs comptent plus que la “liste de fichiers”

La désinfection WordPress vise deux objectifs: supprimer les éléments visibles de la compromission et refermer les portes d’entrée. Les fichiers peuvent être nettoyés, mais si la cause racine reste active, le site rejoue la même scène.

Les logs apportent trois bénéfices très concrets.

D’abord, ils confirment les symptômes. Si vous avez constaté une redirection vers des domaines inconnus, un accès à l’admin en provenance d’IP inattendues ou des requêtes répétées vers wp-login.php, la trace le confirmera. Sans les logs, on reconstruit souvent un récit approximatif à partir de captures d’écran ou de ressenti.

Ensuite, ils donnent des indices sur la méthode. Certains patterns de requêtes ressemblent à des campagnes automatisées, d’autres à une exploration humaine, d’autres encore à un bot qui teste plusieurs endpoints. Cette information oriente vos choix: mise à jour ciblée, durcissement, blocage d’IP, ou rotation de clés.

Enfin, ils permettent de contrôler que la désinfection a réellement “cassé la chaîne”. Si, après nettoyage, les mêmes requêtes persistent et débouchent sur des succès, c’est un signal que rien n’est vraiment terminé.

Dans mon cas le plus marquant, l’équipe avait remplacé les thèmes et le core. Les logs montraient encore des tentatives de connexion réussies quelques heures après la “réparation”, avec un user agent qui n’avait rien à voir avec un navigateur classique. Le mot de passe avait été changé, mais un autre mécanisme d’authentification restait en place. Sans logs, on aurait continué à chercher dans les fichiers au lieu de chercher dans l’identité et les droits.

Clarifier le périmètre avant de lire les traces

Avant d’ouvrir les logs, prenez cinq minutes pour définir ce que vous cherchez et jusqu’où vous devez remonter. Sinon, vous allez vous perdre dans des milliers de lignes, et vous risquez d’“attraper” un faux positif.

Dans l’idéal, vous délimitez:

    la fenêtre de l’incident (date et heure approximatives) l’URL concernée (page impactée, endpoint d’administration, plugin suspect) le type d’activité (redirection, injection de contenu, bruteforce, webshell) vos systèmes impliqués (Nginx ou Apache, PHP-FPM ou mod_php, base de données, WAF éventuel, CDN)

Cette clarification change la lecture. Par exemple, si l’incident est une injection de contenu, vous allez chercher des modifications côté serveur, mais aussi des requêtes qui déclenchent l’affichage. Si l’incident est une prise de compte, vous allez vous concentrer sur les événements d’authentification, les sessions, et les changements de profil.

Un repère simple: le “moment de bascule”

Souvent, il y a un moment précis où tout s’emballe: un pic de requêtes, une erreur PHP répétée, ou un événement de fichier. Chercher ce “moment de bascule” dans les logs vous évite de comparer des heures entières qui n’ont aucun lien avec la compromission.

Dans beaucoup de cas, on repère la bascule par un pic vers wp-admin, par des 404 anormaux, ou par des tentatives vers des fichiers inhabituels dans le document root.

Quels logs consulter en priorité

Les noms changent selon l’hébergement, mais la logique reste la même. L’objectif n’est pas de lire “tout”, c’est de croler entre plusieurs journaux pour obtenir un fil narratif.

Les journaux web (Nginx ou Apache) sont incontournables. Ils vous donnent l’IP source, le chemin demandé, le code HTTP renvoyé, et parfois le referrer et le user agent.

Les journaux PHP (souvent via PHP-FPM ou la configuration PHP de l’hôte) sont essentiels quand il y a une injection via exécution de code, des erreurs de parsing, ou un comportement inattendu de WordPress.

Les journaux d’authentification (SSH si vous avez accès, logs système, parfois logs de contrôle d’accès sur votre plateforme) servent à vérifier si quelqu’un a utilisé un accès administratif au serveur, ou si une attaque a escaladé via des identifiants.

Enfin, si vous avez un outil de surveillance de fichiers, comme des événements de modification ou des instantanés, il complète le tableau. Sur certains serveurs, vous pouvez aussi consulter l’historique des accès aux fichiers, mais ce n’est pas toujours disponible.

Où regarder, concrètement

La plupart des hébergeurs fournissent au moins une interface de consultation, parfois via des chemins standard. Comme les chemins varient, le plus fiable reste de repérer la source dans votre panneau d’hébergement ou via votre documentation interne.

Voici les éléments que je vérifie en premier, dans l’ordre où ils donnent des réponses.

    Nginx ou Apache: accès web, erreurs, éventuellement audit côté reverse proxy PHP-FPM ou logs PHP: erreurs fatales, warnings, stack traces liées à des scripts logs d’accès aux fichiers et exécutions: seulement si vous avez une piste ou un outil dédié logs de connexion: échecs ou réussites SSH, ou événements d’accès admin au niveau système logs WordPress applicatifs (si activés): erreurs de plugins, traces d’authentification, événements de mise à jour

Si vous n’avez accès qu’à une partie des logs, vous pouvez quand même avancer, mais vous devrez être plus prudent dans les conclusions.

Lire les logs d’accès web comme un enquêteur, pas comme un lecteur de roman

Quand vous êtes face à des journaux d’accès, le danger est de se focaliser sur un “méchant chemin” sans relier la chronologie.

Je procède souvent en deux passes.

Première passe: identifier des patterns. Exemples de patterns utiles:

    une rafale de requêtes vers wp-login.php ou wp-admin des requêtes vers des fichiers ou chemins qui ne font pas partie de votre site une série de 301 ou 302 vers d’autres domaines, surtout si le domaine de destination apparaît soudainement des codes 500 ou 403 corrélés avec des erreurs PHP dans l’autre journal

Deuxième passe: corréler. Quand vous voyez une requête qui ressemble à un déclencheur, vous allez vérifier:

    l’heure exacte l’IP source le user agent si la réponse a changé (par exemple un 403 qui devient un 200 après modification) si, dans les logs PHP, des erreurs apparaissent juste après

Cette corrélation est ce qui transforme des “indices” en “preuve raisonnable”.

Un détail qui sauve du temps: la latence entre événements

Les logs ne sont pas toujours parfaitement synchronisés. Il peut y avoir un décalage de quelques secondes entre Nginx, PHP et les logs d’application. Si vous corrélez “au pixel près” vous risquez de rater le lien.

Une approche réaliste consiste à accepter une fenêtre de corrélation, par exemple quelques secondes à une minute selon le volume et la configuration. L’objectif n’est pas la seconde exacte, c’est la séquence logique.

Reconnaître les signatures d’une compromission WordPress

Sans inventer de scénarios universels, il y a des signaux souvent observés. Les logs ne “prouvent” pas à eux seuls, mais ils permettent de prioriser.

Voici les signaux d’alerte que je traite comme des points d’entrée de https://gardewp.fr/nettoyage-malware-wordpress/ triage, pas comme des diagnostics définitifs.

    Pics d’erreurs 500 autour de requêtes vers des plugins ou des endpoints peu utilisés Tentatives répétées vers wp-login.php, XML-RPC ou des URLs qui ressemblent à des scripts inconnus Redirections en série vers des domaines récents ou non liés à votre activité Patterns d’accès depuis des IP ou plages géographiques inattendues, surtout si elles s’enchaînent en quelques minutes Créations ou modifications de fichiers très en dehors des horaires de maintenance (si vous avez une trace de fichiers)

Dans le doute, je considère que l’absence de preuve n’est pas preuve d’absence. Mais les signaux ci-dessus orientent votre action: blocage temporaire, audit ciblé, rotation de secrets, ou vérification de droits.

Corriger après lecture: ce que les logs doivent déclencher

Une désinfection WordPress sérieuse n’est pas uniquement “nettoyer”. Elle implique des actions de réduction de surface et de contrôle.

Une erreur courante consiste à bloquer des IP à la hâte et à oublier le reste. Bloquer une source peut stopper un bruit, mais si l’attaque est basée sur des comptes compromis, vous n’aurez fait que changer l’IP.

À l’inverse, ignorer l’IP vous expose à des récidives qui vous empêchent d’assainir tranquillement.

La bonne approche consiste à transformer chaque observation en hypothèse, puis à tester.

Quelques exemples concrets:

    Si les logs montrent des tentatives d’accès à wp-login.php, je vérifie la politique de mots de passe, l’authentification forte si disponible, et je contrôle les utilisateurs WordPress existants, y compris ceux créés récemment. Si les logs montrent des redirections, je vérifie les fichiers qui interviennent tôt dans la chaîne d’exécution, par exemple les points d’init de WordPress, et je compare l’arborescence avec une version saine. Si les logs montrent des requêtes vers des fichiers PHP dans des chemins inhabituels, je zoome sur les exécutions, mais je vérifie aussi comment ces fichiers ont pu être déposés (droits, FTP, panel d’upload, plugin avec vulnérabilité).

Le trade-off est réel. Un blocage IP peut casser une intégration légitime si votre trafic admin passe par un provider d’entreprise, par exemple. Le bon réflexe consiste à bloquer de façon temporaire ou conditionnelle, puis à observer sur la fenêtre suivante.

L’étape de prudence: ne pas confondre le bruit et l’attaque

WordPress attire des attaques opportunistes, et beaucoup de lignes de logs sont des tentatives de bruteforce ou des probes automatisés. Tout n’est pas une compromission.

La différence se fait sur des indices d’impact: accès réussis, modification de contenu, exécution inattendue, redirection, ou erreurs PHP répétées causées par un payload.

Si vous ne voyez que des 404 ou des tentatives infructueuses, il est possible que vous gériez surtout du bruit. Mais le bruit peut masquer l’aiguillage. C’est pour cela que je préfère toujours chercher des “événements de réussite” dans les logs: codes 200, création d’utilisateur, accès admin, ou corrélations avec des changements de fichiers.

Dans un audit rapide sur un site d’un client, les logs affichaient des milliers de requêtes vers des chemins classiques d’injection. En surface, le site semblait “vivant”. Le tournant a été un détail: une série de requêtes menait à des codes 200 et à une modification du contenu en base dans la même fenêtre. On avait eu une compromise réelle, mais la majorité du trafic restait du scan.

Contrôler l’après: valider que la désinfection a stoppé la chaîne

Une fois la désinfection WordPress faite, il ne suffit pas de “retester le site”. Les logs sont vos yeux pour confirmer que l’attaque s’est éteinte.

Concrètement, je recommande de surveiller pendant une période suffisante. La durée dépend du volume d’attaques et du type d’incident, mais en pratique, observer au moins 24 à 72 heures après la restauration et le durcissement est un minimum utile. Sur certains sites, un cycle plus long est nécessaire, surtout s’il y a des charges déclenchées “plus tard” ou des comptes compromis qui patientent.

Pendant cette phase, vous comparez:

    les codes HTTP sur les endpoints sensibles l’origine des requêtes (IP et patterns) l’apparition de nouvelles erreurs PHP les tentatives d’accès admin et l’activité sur les plugins suspects la présence de requêtes vers des chemins qui n’existent pas

Si les mêmes requêtes continuent sans succès, c’est déjà une victoire partielle. Si les requêtes aboutissent à des réponses utiles, alors votre désinfection n’a pas atteint le fond.

Et si les logs sont incomplets ou trop bruyants ?

C’est fréquent. Certains hébergeurs limitent la rétention, compressent, ou rendent l’export difficile. D’autres ont des niveaux de logs qui noient l’information. Dans ces cas, l’objectif devient “extraire la bonne tranche” plutôt que tout analyser.

Deux stratégies utiles, sans promettre l’impossible:

1) Réduire la fenêtre d’analyse au moment suspect, puis élargir seulement si nécessaire. Les journaux compressés facilitent parfois un export sur une période courte. 2) Concentrez-vous sur les endpoints et sur les codes. Par exemple, cherchez d’abord les codes 200 sur des chemins administratifs, puis les erreurs 500, puis les redirections.

Si vous avez un outil de recherche ou un filtre côté hébergeur, il vaut mieux l’utiliser pour isoler des événements “actionnables” plutôt que d’essayer de lire des pages entières.

Connexions et contrôle d’identité: le point aveugle de beaucoup d’analyses

Je reviens sur un point qui revient trop souvent dans les incidents: la compromission WordPress n’est pas toujours un problème de fichiers.

Les logs serveur peuvent révéler une activité de connexion SSH, ou des accès à un panel d’hébergement. Si quelqu’un a eu accès à l’environnement, il peut modifier des fichiers, ajouter des clés, installer un mécanisme persistant, ou configurer des tâches planifiées.

Même si vous n’avez pas accès aux logs SSH, vous pouvez chercher des traces indirectes, par exemple:

    des modifications de fichiers qui ne correspondent à aucune maintenance des montées de charge autour d’horaires particuliers des requêtes web qui coïncident avec des comportements nouveaux du site

Le diagnostic le plus robuste combine logs web et logs d’exécution ou système. Quand cette combinaison est impossible, il faut compenser par une comparaison d’état: sauvegarde saine, comparaison d’arborescence, et revue des plugins et comptes.

Une courte méthode de triage après incident (pratique, sans miracle)

Quand le stress monte, le triage doit être simple. Je garde généralement une séquence répétable pour ne pas oublier l’essentiel. Vous pouvez l’adapter à votre environnement.

    Isoler la fenêtre de l’incident, puis extraire les logs correspondants Identifier les IP et patterns liés à des succès, pas seulement à des erreurs Croiser logs web avec logs PHP, chercher des corrélations temporelles Vérifier les utilisateurs WordPress et les modifications de rôles dans la période Observer 24 à 72 heures après restauration pour confirmer la disparition des patterns utiles

Le reste, c’est de la spécialisation. Certains cas réclament une analyse plus fine des payloads, d’autres nécessitent un durcissement global, mais cette base évite déjà plusieurs pièges classiques.

Durcissement après désinfection: réduire la surface pour que les logs deviennent calmes

Une fois que vous avez compris “comment”, vous pouvez réduire “comment” on recommence.

Sur un WordPress, je pense souvent en termes de surface:

    accès à l’admin: limiter les attaques, mais aussi réduire les possibilités de comptes faibles plugins: supprimer ce qui n’est pas nécessaire, mettre à jour, et surveiller les extensions qui ont un accès à des fonctions sensibles droits serveur: limiter les uploads et les écritures inutiles dans les chemins exécutables surveillance: mettre en place des alertes sur ce qui a réellement changé pendant l’incident

Attention à un piège courant: durcir sans https://gardewp.fr/ comprendre peut provoquer des pannes. Par exemple, bloquer des requêtes trop largement peut casser le crawl, les webhooks, ou certaines intégrations. Ici, l’intérêt des logs est aussi de mesurer l’impact potentiel. Si vous savez quelles IP et quels endpoints sont réellement en jeu, vos règles sont plus précises.

Ce que je garde en tête pour la suite

La désinfection WordPress devient beaucoup plus fiable quand on accepte une vérité simple: l’incident ne se termine pas à la suppression du fichier suspect. Il se termine quand les traces cessent, quand les accès ne réussissent plus, et quand l’état du site correspond à un état attendu.

Contrôler les logs serveur après incident, c’est transformer un moment de panique en enquête structurée. Vous n’avez pas besoin de tout savoir sur chaque ligne, vous avez besoin de relier les événements entre eux et de faire des actions qui répondent à une hypothèse claire.

Si vous avez été touché récemment, commencez par retrouver la fenêtre exacte, puis cherchez dans les logs ce qui a abouti à un résultat utile pour l’attaquant. C’est souvent là que se cache la différence entre une désinfection “propre” en apparence et une reprise durable.