réparation piratage site wordpress via ACF

Le pirate est entré en 26 secondes et s’est bloqué tout seul : autopsie d’un piratage WordPress

Un mardi midi, fin octobre, un client m’appelle. Il me dit « François, le site ne marche plus, on dirait même qu’il a été piraté mais c’est bizarre ». Je me rends sur le site web concerné : pas d’erreur 500, pas de message de maintenance, pas d’écran blanc de la mort. Juste un mot, en haut à gauche d’une page vide :

ready

Sur la page d’accueil. Sur /wp-admin. Sur chaque page, le site avait l’air de dire « je suis prêt », sauf qu’il ne faisait plus rien d’autre.

Spoiler : c’était un piratage. Un robot est entré dans l’administration du site WordPress et a caché un outil de vol de base de données dans un plugin… et s’est enfermé dehors avec son propre code. Voici l’enquête complète, et surtout ce qu’elle vous apprend sur la sécurité de votre propre site.

L’enquête : du symptôme au fichier coupable

Toute la partie publique du site était bloquée, l’espace d’administration aussi. J’ouvre Filezilla qui me permet d’accéder à tous les fichiers du site. Le .htaccess et l’index.php étaient bien d’origine. En y réfléchissant, l’adresse /wp-admin ne passe pas par les règles de réécriture de WordPress. Si elle aussi affiche « ready », le problème est ailleurs.

En fin limier que je suis, j’ai donc procédé par élimination, une couche après l’autre :

  1. Le serveur. J’ouvre un fichier statique, readme.html. Il s’affiche normalement : la requête arrive bien dans le bon dossier, le DNS n’y est pour rien.
  2. PHP. Je dépose un petit script de diagnostic. PHP fonctionne, et aucun fichier n’est exécuté avant WordPress.
  3. WordPress. Le coupable est donc dans WordPress lui-même. Je liste les fichiers PHP modifiés ces dernières 48 heures. Un seul ressort : acf.php, le fichier principal d’Advanced Custom Fields, modifié le matin même à 07:39.

Un seul fichier modifié est un détail qui saute aux yeux. Une vraie mise à jour de plugin réécrit des centaines de fichiers. Quand seul le fichier principal bouge, quelqu’un est passé par là.

Confirmation en dix secondes : je renomme le dossier du plugin, et le site revient. Puis je compare tous les plugins aux empreintes officielles publiées par wordpress.org. Verdict : un seul fichier modifié sur tout le site, celui-là.

À ce moment, je sais que le coupable du crash du site est le plugin ACF. Mais il n’est pas encore établi qu’il s’agit d’un piratage.

Je sais que le fichier a été modifié à 7h39 ce jour, je me rends donc dans le Manager OVH du client pour accéder aux logs journaliers.

Les logs sont le registre des connexions au site : ils retracent toutes les connexions au site et permettent par exemple de pister les robots d’indexation des moteurs de recherche ou, comme ici, de diagnostiquer les actions et points de passage d’un pirate.

Accès aux logs OVH
Pour accéder aux logs OVH, il suffit de cliquer sur « Voir les logs » dans l’onglet « Statistiques et logs » de votre hébergement
Accès aux logs journaliers OVH
Vous trouverez les logs journaliers bruts. Ici ce sont les logs « Web » que je venais chercher

Ces fameux logs du serveur ont tout raconté. L’attaque entière a duré deux minutes et demie. Et le moins que l’on puisse dire, c’est qu’elle n’a rien eu de sophistiqué :

HeureCe qui se passe
07:37:23Une première adresse IP tente trois connexions. Trois échecs.
07:37:53Une seconde IP se connecte. Du premier coup, avec un compte administrateur.
07:38:14Elle ouvre l’éditeur de fichiers intégré à WordPress (Extensions → Éditeur de fichiers).
07:38–07:39Elle tente d’écrire dans huit plugins à la suite, une écriture toutes les 3 à 5 secondes. Une seule réussit.
07:39:27Le code malveillant est enregistré dans acf.php.
07:39–07:40Elle enchaîne upload de thème, upload de plugin, médiathèque, xmlrpc.php… Tout répond « ready ».
07:40:25Dernière tentative de reconnexion, puis plus rien.

Ce qui est sûr ici, c’est que personne n’était derrière un écran. Une requête par seconde, des adresses tapées en dur, la même séquence rejouée trois fois à l’identique, et trente pages « ready » encaissées sans changer de stratégie : c’était un script qui déroulait sa liste en dehors de toute action humaine.

Ce que faisait le code, et pourquoi le pirate s’est bloqué tout seul

Le code ajouté en tête du fichier tenait en une cinquantaine de lignes. C’est un outil de vol de base de données, qui réagit selon le paramètre ajouté à l’URL :

  • ?test répond « ok » : le pirate vérifie que sa porte est en place.
  • ?diag liste le chemin du serveur et toutes les tables de la base.
  • ?dump exporte en une seule réponse le fichier wp-config.php (identifiants de la base compris), tous les utilisateurs avec leurs mots de passe chiffrés, toutes les options (là où dorment les clés API des plugins) et les tables des plugins.
  • Sans paramètre, il affiche « ready » et s’arrête.

Concrètement, le code pirate avait vocation à télécharger l’intégralité des données du site dont, évidemment, les données les plus sensibles.

Ce code était conçu pour vivre dans un fichier à part, qu’on appelle seulement quand on en a besoin. Collé en tête d’un plugin chargé à chaque page comme il l’a fait dans ce cas, le code malveillant interceptait toutes les requêtes, y compris celles du pirate. Sa propre porte dérobée lui a fermé l’administration au nez. Les logs de la journée ne montrent aucun appel aux fonctionnalités de vol de données. La porte a été posée, mais jamais utilisée. Aucune donnée n’est sortie.

La vraie cause : un mot de passe déjà public

Dans le cas de ce piratage : on ne parle pas de faille de plugin ou de serveur mal configuré. Ce n’est pas non plus une attaque spectaculaire et engagée comme on en parle parfois dans la presse. C’est le scénario le plus simple qui s’est produit : le robot avait le bon identifiant et le bon mot de passe, tout simplement.

J’ai vérifié l’adresse e-mail du compte admin hacké sur Have I Been Pwned. Elle apparaissait dans plusieurs compilations de credential stuffing : des listes de couples e-mail + mot de passe en clair, issues de fuites d’autres sites, qui circulent librement. L’une d’elles, indexée en 2025, contient 2 milliards d’adresses.

Résultat Have I Been Pwned : adresse présente dans 4 fuites de données
Capture d’écran du scan Have I Been Pwned de l’adresse mail en question. L’outil est gratuit, profitez-en pour vérifier votre adresse e-mail surtout si celle-ci ouvre des accès à des données sensibles

Le principe est bête comme chou mais redoutable. Un robot prend ces listes d’identifiants et mots de passe et teste chaque couple sur des milliers de sites. Le mot de passe a été réutilisé ici ? La porte s’ouvre.

Ici, le site était sur un sous-domaine du même nom de domaine qui gérait l’e-mail. Pour illustrer sans dévoiler le client : le site piraté était https://intranet.lesite.com et l’email concerné hello@lesite.com. Et même si ce site web est un intranet qui n’est indexé par aucun moteur de recherche, les sous-domaines d’un site sont publics : chaque certificat SSL est inscrit dans des registres consultables par tous. De plus, des scanners parcourent Internet en continu à la recherche de pages de connexion WordPress.

Dès lors, mon client qui utilisait souvent, bien que pas toujours, le même mot de passe d’un site et d’une application à l’autre venait de se faire pincer.

Résumé de l’affaire :

1 – Un site tiers s’est fait voler les identifiants de mon client, qui ont fini dans des listes partagées entre pirates.

2 – Un autre pirate sorti de nulle part a finalement tenté de se connecter à l’intranet du client un mardi matin avec les identifiants et mots de passe volés. Bingo : un combo identifiant / mot de passe volé était également utilisé sur ce site.

3 – Le robot fait sa popote et parvient à coller son code malveillant dans un plugin initialement parfaitement légitime.

4 – Le code malveillant fonctionne bien mais, du fait de son lieu d’implantation, bloque le site au point que le pirate lui-même ne peut plus l’utiliser pour voler la base de données.

5 – Votre humble serviteur diagnostique, nettoie tout et prend les mesures pour que ce pirate ne puisse plus exploiter la même faille.

Ce qui a été préconisé pour prévenir de nouvelles attaques du genre :

Après avoir retiré le code malveillant et remis en place le site au propre, voici les actions préconisées au client :

  • Vérifier les adresses sur haveibeenpwned.com, et surtout celle des comptes administrateurs WordPress.
  • Un mot de passe unique par service, géré par un gestionnaire reconnu. Si l’un fuit, il n’ouvre qu’une porte.
  • Activer la double authentification sur les comptes admin. Avec elle, le mot de passe fuité n’aurait servi à rien. Le module Login Security de Wordfence le fait gratuitement.
  • Désactiver l’éditeur de fichiers de WordPress, l’outil exact utilisé par le robot malveillant dans notre cas : define( ‘DISALLOW_FILE_EDIT’, true ); à placer dans le wp-config.php.
  • Limiter les comptes administrateurs à ceux qui en ont vraiment besoin.
  • Protéger la boîte mail liée au compte admin. Celui qui y accède peut réinitialiser le mot de passe WordPress.
  • Faire des sauvegardes hors de l’hébergement. Le jour où ça tourne mal, ces sauvegardes externes sont salvatrices.

Et si votre site affiche un jour quelque chose d’étrange, ne réinstallez pas tout de suite : gardez le fichier suspect et regardez les logs. C’est la seule façon de savoir par où l’intrus est entré, et donc de l’empêcher de revenir.

Ici, l’histoire se termine bien : le logiciel pirate n’a « que » planté le site et n’a jamais réussi à en extraire des données, mais ce n’est pas passé loin quand même. La seule faute de sécurité qui a permis cela est la réutilisation des mêmes identifiants et mots de passe de la part du compte admin du client sur plusieurs sites, dont un qui a fait l’objet d’une fuite de données. Selon le site attaqué, le pirate aurait pu réussir à exporter l’intégralité des données du site et donc, avec cela, des données sensibles de clients ou utilisateurs. Les enjeux sont vite énormes et la sécurité de vos sites est naturellement à prendre au sérieux. D’autant plus avec des outils d’automatisation, et désormais d’IA, de plus en plus accessibles aux pirates.

Vous voulez savoir si votre site WordPress résisterait à ce robot ? Je fais le point avec vous.

FAQ

Mon site WordPress affiche « ready » sur une page blanche, que faire ? C’est très probablement le signe d’une porte dérobée, WordPress n’intègre pas ce genre d’affichage par défaut. Cherchez un fichier PHP modifié récemment, en particulier le fichier principal d’un plugin. L’attaque du cas présentée ici peut être retrouvée grâce à au marqueur « /* wt payload v1 */ ». Gardez une copie du fichier, puis remplacez le plugin par une version officielle.

Comment savoir si mon site WordPress a été piraté ? Comparez vos fichiers aux versions officielles : un scan Wordfence le fait automatiquement. Contrôlez aussi la liste de vos administrateurs et les fichiers PHP modifiés ces derniers jours.

Changer mon mot de passe suffit-il après un piratage ? Non. Il faut aussi supprimer le code ajouté, déconnecter toutes les sessions (en régénérant les clés de wp-config.php), changer le mot de passe de la base de données et activer la double authentification. Et changer ce mot de passe partout où vous l’aviez réutilisé.

C’est quoi, le credential stuffing ? Une attaque qui teste en masse des couples e-mail + mot de passe volés sur d’autres sites. Elle ne fonctionne que si vous réutilisez vos mots de passe et la double authentification la neutralise.