Désinfection WordPress : contrôler les sessions et tokens compromis

Quand on parle de “désinfection” WordPress, on pense souvent à la partie visible du problème: supprimer des fichiers injectés, désactiver des plugins suspects, corriger une faille. C’est indispensable. Mais dans beaucoup d’incidents que j’ai vus, la vraie difficulté commence après le nettoyage. Le site est “propre” sur le disque, pourtant des visiteurs voient encore des redirections, des comptes reprennent vie, ou l’infection revient dans les heures qui suivent.

La cause la plus frustrante n’est pas toujours un malware qui tourne en boucle. C’est un accès persistant, maintenu par des sessions et des tokens compromis. Tant qu’ils restent valides, l’attaquant peut réintroduire du code, modifier des articles, réactiver des comptes, et contourner vos mesures comme si rien n’avait été fait. Contrôler et invalider ces sessions et ces tokens, c’est ce qui sépare parfois un incident “réparé” d’une “désinfection” réellement durable.

Le piège classique: supprimer le code, laisser les portes ouvertes

Une session, dans WordPress, n’est pas qu’un concept abstrait. Dans la pratique, cela correspond à des cookies (de type connexion) et à des métadonnées côté base. Les tokens peuvent être multiples:

    cookies de connexion WordPress (liés à des clés et salting dans le fichier wp-config) cookies “remember me” si vous avez une option de type session longue jetons de plugins (authentification SSO, “remember token”, refresh tokens) tokens de REST API, si un plugin expose des endpoints à des clients internes paramètres ou clés stockés dans la base (options, usermeta), utilisés pour valider une session même après modification des rôles

Dans un scénario réaliste, l’attaquant obtient un cookie Admin. Vous nettoyez les fichiers, vous changez les mots de passe, puis vous observez que des modifications continuent. Ce n’est pas forcément parce que vous n’avez pas supprimé le bon malware. C’est parce que le cookie permet encore une authentification valide tant que WordPress considère la session comme cohérente avec ses clés actuelles.

J’ai déjà vu un site “désinfecté” en une heure, puis recontaminé le soir même. Le nettoyage avait été fait rapidement, mais les clés d’authentification n’avaient pas été renouvelées et les cookies de l’admin n’avaient jamais été invalidés. Résultat: l’attaquant était toujours dans la maison, même après avoir retiré les meubles qu’il avait apportés.

Comprendre ce que vous devez invalider, côté WordPress et au-delà

WordPress, par défaut, gère l’authentification via des cookies signés. Ces cookies dépendent de clés et de “salts” configurés dans wp-config.php. Quand ces valeurs changent, WordPress invalide les sessions existantes, car la signature ne matche https://gardewp.fr/nettoyage-malware-wordpress/ plus.

Ensuite, il y a la réalité des déploiements modernes: reverse proxy, CDN, WAF, plugins d’authentification tierce, mécanismes “remember” ou “single sign on”, et parfois des caches de pages côté serveur ou edge. Même si WordPress invalide correctement les sessions, un cache peut servir des contenus modifiés par l’attaquant, ce qui donne l’impression que “l’infection revient”, alors que c’est seulement un contenu persistant. Inversement, l’infection peut revenir parce que vous invalidez mal l’état d’auth, tout en croyant que “tout est changé”.

C’est pour cela que la désinfection sérieuse doit traiter au moins trois couches:

L’état d’auth côté WordPress (cookies et clés de signature) L’état d’auth côté base (métadonnées qui participent à la validation) Les états externes (sessions maintenues par un proxy, tokens gérés par des plugins, mécanismes SSO)

Les signes qui indiquent que des tokens compromis restent actifs

Avant d’agir, il est utile de reconnaître le pattern. Quand le problème est seulement “des fichiers malveillants”, vous voyez souvent des pages corrompues, des liens injectés, des redirections, des scripts en public, puis un retour rapide à la normale après suppression. Quand des sessions et tokens compromis sont en jeu, le pattern est plus “comportemental”: l’accès revient, les modifications sont refaites, des comptes semblent activés sans raison.

Quelques signaux concrets, observables sans supposer:

    des modifications dans la base (articles, pages, options) juste après vos actions, souvent avec un horodatage très proche de la dernière intervention des connexions depuis des IP ou des user agents que vous n’attendez pas, y compris des connexions “réussies” à des heures où vous avez déjà changé des mots de passe des tentatives répétées sur les endpoints wp-login, xmlrpc.php, ou sur des requêtes REST effectuées sans correspondre à votre trafic habituel des actions d’admin qui semblent “cohérentes” du point de vue WordPress (droits normaux), mais qui ne sont pas déclenchées par un opérateur humain l’exécution de tâches planifiées (WP-Cron) avec des paramètres qui ne ressemblent pas à votre configuration habituelle

Si plusieurs de ces signes sont présents, vous avez probablement un accès persistant. Là, le simple nettoyage de fichiers ne suffit pas.

Méthode de désinfection orientée “accès”: d’abord casser la continuité

Je recommande de penser l’intervention en deux temps. D’abord, couper la continuité d’accès de l’attaquant. Ensuite seulement, nettoyer à fond et durcir.

Voici un cadre d’action pragmatique. L’objectif n’est pas la perfection théorique, c’est d’empêcher la prochaine réinjection.

    Passez le site en maintenance si possible, ou au minimum limitez les actions à votre IP, pour réduire le bruit et empêcher les actions de l’attaquant pendant que vous intervenez. Vérifiez les journaux: connexions wp-login, activité administrative, accès à xmlrpc.php, et requêtes REST si vous avez des logs applicatifs ou un WAF/WAF logs. Changez les clés d’authentification dans wp-config.php (AUTH KEY, SECUREAUTH KEY, LOGGEDIN KEY, NONCEKEY et leurs homologues SALT). Cela invalide les cookies de session existants. Forcez une réinitialisation des secrets et des jetons liés à votre environnement: déconnectez les comptes, désactivez temporairement les plugins d’auth externe, et supprimez les refresh tokens si un plugin enregistre ce type de flux. Nettoyez ensuite le code et la configuration, sans oublier les cron, les utilisateurs et les rôles, et enfin purgez caches et headers si un contenu a été persisté.

Ce cadre mélange volontairement des actions “dans le bon ordre”. Changer les clés d’auth avant un grand nettoyage peut sembler contre-intuitif, mais c’est souvent ce qui évite de travailler pendant qu’un accès valide continue.

Cas particulier: vous devez garder l’accès pendant l’intervention

Changer les clés d’auth invalide votre propre session d’administration. C’est normal, et c’est précisément le but. Prévoyez le coup: connectez-vous depuis un navigateur “propre”, et gardez un accès alternatif (console serveur, SSH, accès panneau hébergement) au cas où votre compte serait aussi déconnecté avant que vous ayez fini.

Sur un site où plusieurs admin partagent l’accès, demandez-leur de se reconnecter après changement des clés. Si vous avez un SSO, ce sera plus délicat, car le token SSO peut garder un état côté fournisseur. Dans ce cas, vous cassez l’état WordPress, mais vous devez aussi vérifier le côté SSO.

Invalider concrètement les sessions et tokens WordPress

1) Renouveler les clés et salts dans wp-config.php

C’est l’action la plus structurante. WordPress utilise ces valeurs pour signer et valider l’authentification. Si vous les changez, les cookies de connexion déjà émis ne pourront plus être validés.

Concrètement, vous remplacez les valeurs de:

    AUTH_KEY SECURE AUTHKEY LOGGED INKEY NONCE_KEY et les variables SALT correspondantes (AUTH SALT, SECUREAUTH SALT, LOGGEDIN SALT, NONCESALT)

Ensuite, attendez un peu que les requêtes arrivent et observez les logs de connexion. Vos propres connexions seront à refaire, mais vous aurez une rupture nette de la continuité.

2) Forcer la reconnexion et nettoyer les traces côté utilisateurs

Le renouvellement des clés invalide les cookies, mais vous devez aussi vérifier les comptes. Je ne fais pas de supposition sur “qui était compromis”. Je compare l’existant à ce que j’attendrais en conditions normales.

Dans la base, WordPress stocke des métadonnées dans des tables comme usermeta, notamment des options liées aux sessions selon les versions et plugins. En pratique, au-delà des clés, il faut:

    supprimer les utilisateurs créés récemment sans justification révoquer ou supprimer les rôles admin inattendus vérifier l’historique de modification (si vous l’avez) et surtout la cohérence avec vos opérations récentes

Si un attaquant a créé un compte, il peut continuer à agir avec un mot de passe qu’il connaît encore. Changer les mots de passe est nécessaire, mais attention à un détail: si vous changez les mots de passe sans invalider les cookies, l’attaquant peut garder une session active et continuer à gérer le site. D’où l’importance de l’ordre.

3) Stopper les plugins qui gèrent des tokens

Un grand nombre d’incidents “auth persistante” ne vient pas de WordPress lui-même, mais de plugins qui implémentent leur propre logique d’authentification, de refresh tokens, de “remember” ou d’intégration externe.

Exemples de cas que j’ai rencontrés:

    plugins de sécurité ou firewall qui ont un mécanisme d’auth externe plugins OAuth, API clients, ou connecteurs vers des outils systèmes “pro” qui stockent des clés et jetons dans la base

La règle que j’applique: après un incident, je désactive temporairement tout ce qui touche à l’auth, puis je réintroduis graduellement. Cette approche réduit le risque de garder un token caché dans un plugin.

4) Vérifier la couche proxy, CDN et session de bord

Même si WordPress invalide ses cookies, un reverse proxy ou un CDN peut avoir un cache qui sert du contenu modifié. Cela ne revalide pas un cookie, mais ça donne une fausse impression que l’attaque “continue”.

De plus, certains environnements peuvent faire de la rétention de session côté edge, en particulier si vous utilisez des mécanismes spécifiques de gestion d’état. Je conseille de:

    purger le cache CDN après nettoyage final vérifier les règles WAF ou mécanismes “allowlist” qui auraient pu être configurés par un attaquant inspecter la redirection et les règles de rewrite si vous avez un fichier .htaccess ou des règles applicatives

L’objectif est simple: séparer un effet de cache d’une vraie réauthentification persistante.

Netoyer le malware ensuite, sans rater ce qui se “cache” après l’accès

Une fois l’accès cassé, vous pouvez nettoyer efficacement. Mais là encore, je vois souvent une erreur: nettoyer uniquement les fichiers visibles, sans chercher la persistance.

Après un incident, examinez les zones qui se modifient facilement:

    fichiers PHP ajoutés ou modifiés dans le thème et surtout dans des endroits “discrets” de plugins fichiers en dehors des répertoires attendus, ou téléchargements supplémentaires via uploads scripts dans wp-content/uploads, notamment si l’attaquant a caché des charges dans des images ou archives puis déclenché via un hook cron malveillants, qui planifient des actions dans le futur options WordPress modifiées, comme des paramètres de redirection, des URL cibles, ou des configurations de plugins

Le nettoyage malware WordPress, s’il est fait sérieusement, doit aussi vérifier les droits et propriétaires sur le système de fichiers. Un attaquant qui a réussi à écrire peut avoir laissé des droits trop permissifs. Même en supprimant le code, une permission mal calibrée peut faciliter une réinjection ultérieure.

Évaluer les risques selon le type d’intrusion

Il existe des degrés. La façon de traiter les sessions et tokens dépend parfois de la nature du compromis.

    Si vous suspectez un seul navigateur de session compromise, changer les clés d’auth et réinitialiser les mots de passe des admins peut suffire, à condition d’éliminer l’origine de l’accès. Si vous suspectez un compte admin compromis avec persistance, vous devez faire plus que changer un mot de passe. Révoquez les comptes inutiles, vérifiez les plugins installés, et invalidez les sessions via les clés. Si vous suspectez une compromission serveur, l’approche change. Invalider les cookies ne protège pas d’une recontamination. Dans ce scénario, je traite en priorité l’intégrité du serveur et des dépôts applicatifs, avec restauration depuis sauvegarde clean si nécessaire.

Je ne propose pas de “tout refaire” par réflexe, mais je traite plus strictement dès que les indicateurs montrent une action au-delà de la couche WordPress.

Exemple concret d’une séquence d’intervention (sans magie)

Sur un site vitrine avec trafic faible, l’équipe avait fait un nettoyage de fichiers et mis à jour les plugins. Le lendemain, une page avait de nouveau une redirection vers une destination douteuse. Les logs montraient une connexion admin réussie sans correspondance avec les horaires d’équipe. Les clés d’auth n’avaient pas été renouvelées.

La correction a suivi un ordre simple:

1) passage en maintenance et blocage temporaire de l’accès admin depuis des IP non reconnues

2) changement des clés et salts dans wp-config, puis reconnexion forcée des admins 3) réinitialisation des mots de passe de tous les comptes ayant des rôles d’administration 4) désactivation temporaire des plugins liés à l’auth et vérification des utilisateurs créés récemment 5) seulement ensuite, nettoyage complet des fichiers modifiés et purge caches

Ce que je retiens de ce cas, c’est le “temps gagné” grâce à l’invalidation d’auth. Pendant que l’équipe nettoyait, l’attaquant pouvait encore modifier le contenu. Après changement des clés, les modifications cessent net. Cela a aussi rendu l’analyse forensique plus claire, car les variables se stabilisent.

image

image

À quels points faut-il être particulièrement strict

Il y a des endroits où une session compromise peut continuer à agir même si vous changez le reste. J’ai l’habitude de vérifier ces points en priorité, surtout si l’attaque a laissé des redirections ou de faux contenus.

Mini-check des mécanismes d’accès souvent oubliés

    clés AUTH et SALT dans wp-config non renouvelées comptes admin créés ou promus récemment plugins d’auth ou connecteurs externes toujours actifs cron ou tâches planifiées qui continuent après nettoyage cache CDN ou reverse proxy qui masque le “retour au normal”

Cette liste tient en peu de lignes, mais elle fait gagner beaucoup de temps, parce qu’elle cible ce qui maintient l’accès ou le rend invisible.

Quand vous devez restaurer plutôt que “corriger”

Parfois, il ne s’agit pas seulement d’invalider des tokens. Si la compromission est large, si des fichiers système ou des scripts de déploiement ont été modifiés, ou si la machine d’hébergement est douteuse, vous pouvez tourner en rond.

Restaurer depuis une sauvegarde clean est souvent la voie la plus rapide, surtout si vous avez une sauvegarde fiable avant l’incident. Dans un doute, je préfère le coût d’une restauration propre plutôt que la lenteur d’une chasse au comportement, parce que l’attaque peut se réinstaller via un mécanisme racine.

La question que je me pose n’est pas “est-ce que je peux corriger”, c’est “est-ce que je peux être sûr que l’accès persistant est éliminé”. Si la réponse est fragile, je privilégie une restauration, puis je réapplique les mises à jour et durcissements.

Durcir après la désinfection, pour éviter la répétition

La désinfection sans durcissement finit souvent par une nouvelle infection. Les sessions et tokens compromis sont une conséquence, pas la cause unique. La cause peut être un mot de passe faible, une faille dans un plugin, une mauvaise configuration, ou une compromission via une session déjà active ailleurs.

Après l’incident, je réduis les chances de répétition:

    appliquer les mises à jour WordPress, thèmes et plugins supprimer les thèmes et plugins inutilisés (moins de surface, moins de bugs) renforcer la gestion des mots de passe et limiter les comptes admin surveiller les logs de connexion et les événements d’administration utiliser une stratégie de mise en quarantaine pour les plugins sensibles, notamment ceux qui gèrent des autorisations ou un accès API

Et surtout, je garde la discipline de revalider l’auth au moindre doute: si un incident touche à la connexion, je traite la logique de sessions comme une pièce maîtresse, pas comme un détail.

Ce que “contrôler les sessions et tokens” change vraiment

La désinfection WordPress, surtout quand des sessions et tokens compromis sont impliqués, ne se résume pas à un correctif technique. Ça change votre posture d’intervention.

image

Vous ne cherchez plus seulement à supprimer des traces. Vous coupez la capacité d’action. Vous mettez l’attaquant hors-jeu, même s’il a trouvé un chemin vers l’administration. Et une fois l’accès cassé, votre nettoyage devient plus fiable, plus mesurable, et moins coûteux en temps.

En pratique, la meilleure réussite que j’ai vue n’était pas celle qui a retiré le code le plus vite. C’était celle qui a stoppé la continuité d’accès en premier. Ensuite seulement, le reste a suivi, proprement, sans recontamination mystérieuse.

Si vous devez retenir une seule idée, c’est celle-ci: dans un incident WordPress, une session valide peut être aussi dangereuse qu’un fichier malveillant. Les deux doivent être traités, et dans le bon ordre.