Forensic WordPress : Comment j’ai neutralisé un Botnet agressif en 4h

Le 30 janvier 2026, à 15h50, j’ai pris en charge une infection critique sur une instance WordPress hébergée chez Infomaniak. Ce n’était pas une simple injection de liens de spam, mais une compromission par Botnet persistant. L’objectif : transformer le serveur en nœud de commande pour une campagne de cyberattaques à grande échelle.
Chronomètre : 4 heures pour passer d’un site wordpress totalement compromis à une infrastructure durcie et saine.

Analyse médico-légale (Forensics) et vecteur d’entrée

Tout commence par l’étude des journaux d’accès du serveur. L’IP 154.213.165.0, localisée dans un centre de données à Berlin, ne se contentait pas de visiter le site, elle le mitraillait. Le bot exploitait une vulnérabilité d’exécution de code à distance sur des extensions obsolètes de la suite Crocoblock. En pénétrant le système, l’attaquant a déployé un arsenal sophistiqué, notamment un faux plugin nommé DrSQL. Ce dossier contenait un script nommé backup.php qui, loin de sauvegarder les données, servait de point d’entrée pour injecter des WebShells polymorphes comme Alfa-Rex ou WTS-Shell dans les recoins les plus sombres du site.
L’infection n’était pas superficielle. Le bot avait modifié plus de 100 fichiers vitaux dans les répertoires wp-admin et wp-includes en utilisant la technique du timestamping, une méthode consistant à falsifier les dates de modification des fichiers pour tromper une surveillance humaine visuelle. Onze comptes administrateurs fantômes avaient déjà été créés en base de données pour assurer une reprise de contrôle permanente.
Beaucoup auraient, dès le départ, simplement remplacé les dossiers /wp-admin/ et /wp-includes/. Pourtant, ce n’est pas la bonne approche.
Sans avoir identifié la source de la persistance, cette action fait surtout perdre du temps : pendant que vous essayez de reprendre la main sur le site, le bot peut se répliquer immédiatement dans les répertoires système. Pendant que vous contrôlez les extensions, vous risquez de passer à côté de dossiers cachés ou de mécanismes de réinfection — et l’infection revient alors quasi instantanément.
En réalité, remplacer les fichiers ne doit intervenir qu’en toute fin de procédure, après un travail complet de neutralisation de la source, d’éradication de la persistance et de sécurisation de l’environnement.

Pourquoi j’interdis l’utilisation de Windows
pour l’analyse de malware

C’est ici que ma méthodologie se distingue radicalement d’un nettoyage amateur.

Face à une infection de cette ampleur, je n’utilise jamais de machine sous Windows (d’ailleurs j’en ai plus depuis longtemps)pour l’analyse des fichiers corrompus.

Windows possède des services d’aperçu automatique et des processus d’indexation qui peuvent déclencher par accident l’exécution de charges utiles cachées. Un malware peut être polyglotte :
il peut se présenter sous l’extension .php mais dissimuler un script Shell (.sh) redoutable.

Interdis l'utilisation de Windows pour l'analyse de malware

J’ai même connu le champion du monde ! Un pro qui désactive son antivirus, car il refusait de télécharger les fichiers en FTP !

webmaster67
Pour garantir une sécurité totale, j’importe les dossiers infectés dans un bac à sable strictement isolé sous un système Linux. Le point de montage du disque dur est configuré avec l’option de sécurité no-exec.

Cette restriction logicielle empêche le processeur d’exécuter la moindre instruction provenant de ce répertoire. Le malware se retrouve paralysé, ce qui me permet d’ouvrir le code source et de l’étudier sans que jamais une seule ligne de code malveillante ne puisse s’activer ou tenter d’infecter mon propre réseau.

L’autopsie clinique : Analyse du contenu du bac à sable

Une fois les fichiers isolés dans mon environnement no-exec, l’étape cruciale de l’analyse commence. C’est ici que l’on passe de la simple suspicion à la certitude technique. Grâce à des outils d’analyse de flux et de recherche de chaînes de caractères (strings), je décortique la charge utile sans jamais lui donner la moindre chance de s’activer.
L’analyse du contenu révèle souvent une architecture en « poupées russes ». Derrière un fichier aux apparences anodines comme functions.php, je découvre des blocs de code obfusqués en Base64 ou compressés avec gzinflate. Le but est simple : rendre le script illisible pour les scanners automatiques de l’hébergeur. En forçant le décodage dans mon bac à sable, je mets à jour les véritables intentions du botnet : des requêtes vers des serveurs de commande (C&C) situés à l’étranger et des routines de scan pour infecter d’autres sites sur le même serveur.
Cette dissection me permet également d’identifier les signatures uniques du malware. Je ne cherche pas seulement des virus connus, je traque des comportements. Je repère les fonctions de « callback » que le pirate utilise pour reprendre la main, ainsi que les « portes dérobées » (backdoors) dissimulées dans les dossiers d’images ou de langues. Cette compréhension profonde du mode opératoire de l’attaquant est ce qui me permet de garantir que le nettoyage suivant sera définitif, et non un simple pansement temporaire.
// //
├── [4.0K]  jupiterx <-- Lui c'est le thème utiliser OK !
│   ├── [ 399]  comments.php
│   ├── [ 397]  footer.php
│   ├── [ 639]  full-width.php
//  //
│   ├── [98.5K]  functions.php <-- un functions de ce poid ou c'est un gros bidouillage ou c'est une relance automatique de multiplication !
//  //
│   ├── [ 393]  header.php
│   ├── [ 313]  index.php
│   ├── [4.0K]  lib
│   │   ├── [4.0K]  admin
│   │   │   ├── [4.0K]  assets
│   │   │   │   ├── [4.0K]  images
│   │   │   │   └── [4.0K]  lib
│   │   │   ├── [ 17K]  assets.php
│   ├── [ 18K]  LICENSE
│   ├── [3.0K]  new-customizer.md
│   ├── [852K]  reademe.txt<--- Presque passer inaperçue !
C'est un fichier .sh disimuler ! à 852K c'est pas un fichier texte légitime à coup sure !
│   ├── [ 122]  rtl.css
│   ├── [ 72K]  screenshot.jpg
│   ├── [ 257]  sidebar.php
│   ├── [ 406]  sidebar-primary.php
│   ├── [ 408]  sidebar-secondary.php
│   ├── [2.3K]  style.css
│   └── [3.6K]  wpml-config.xml
├── [4.0K]  twentytwentyfive
//
//
├── [4.0K]  wordpress-seo
│   ├── [4.0K]  admin
│   │   ├── [2.4K]  admin-settings-changed-listener.php
│   │   ├── [4.0K]  ajax
│   │   │   ├── [1.6K]  class-shortcode-filter.php
│   │   │   ├── [2.0K]  class-yoast-dismissable-notice.php
│   │   │   └── [3.4K]  class-yoast-plugin-conflict-ajax.php
│   │   ├── [ 11K]  ajax.php
│   │   ├── [4.0K]  capabilities
│   │   │   ├── [2.2K]  class-abstract-capability-manager.php
│   │   │   ├── [ 763]  class-capability-manager-factory.php
// //   // //
│   │   │   ├── [3.0M]  class-capability-manager-integration.php <-- regarder le poid de cette classe face au autres !

//  //  //  //
│   │   │   ├── [ 876]  class-capability-manager.php
│   │   │   ├── [1.9K]  class-capability-manager-vip.php
│   │   │   ├── [1.2K]  class-capability-manager-wp.php
│   │   │   ├── [2.3K]  class-capability-utils.php
│   │   │   └── [3.2K]  class-register-capabilities.php

// 
├── plugins
│   ├── aatdgetgdg <-- Alors lui je sais pas qui c'est ?
│   ├── [1.4K]  backup.php
│   └── [ 52K]  main.txt<- ce n'est pas un TXT mais un .sh
│   ├── wpnganvgei <--  Et lui Alors ?
│   ├── [1.4K]  backup.php
│   └── [ 52K]  main.txt
Dans le cadre d’une infection WordPress, j’utilise tree pour cartographier rapidement les fichiers rapatriés et repérer ce qui ne devrait pas être là. L’objectif est d’obtenir une vue globale de l’arborescence, y compris les fichiers/dossiers cachés (souvent utilisés pour la persistance), afin d’identifier des emplacements anormaux : répertoires inattendus, profondeurs de dossiers incohérentes, doublons, ou fichiers au nom suspect.

En cybersécurité, on appelle ça le « Hide in plain sight ».

L’erreur volontaire : En écrivant reademe.txt au lieu de readme.txt, le pirate s’assure que si un script de nettoyage automatique cherche les fichiers readme.txt standards pour les vérifier, il passera à côté de celui-là.
Le « Typosquatting » de fichier : L’œil humain est habitué à voir des fichiers readme.txt dans chaque dossier de plugin ou de thème. Ton cerveau « saute » le mot parce qu’il pense le connaître. La petite faute de frappe (reademe) est juste assez subtile pour que l’administrateur pressé ne la remarque pas, tout en gardant une extension .txt qui rassure.
Le contraste de poids : C’est là que j’ai l’œil de lynx. Un readme.txt pèse normalement entre 2 et 10 Ko. Le voir à 852 Ko, c’est l’alerte rouge immédiate. C’est comme voir une enveloppe de courrier qui pèse 5 kilos : tu sais qu’il n’y a pas qu’une lettre à l’intérieur.

Votre site affiche des alertes ou semble ralenti ?

Ne laissez pas un botnet étranger utiliser votre serveur pour des activités cybercriminelles.
Chaque minute compte pour votre SEO et votre réputation

Le résultat de l’analyse approfondie

Comme je n’aime pas rester sur ma fin j’ai voulu en savoir plus.
j’ai pris le temps après avoir corriger le site et placer un systeme de sécurité , je me suis pencher sur cette infection et là !
SURPRISE ! Made in china
La méthode bien répandu chez les hackers.
En poussant l’analyse du Whois sur l’adresse IP assaillante, j’ai pu identifier qu’elle appartenait au réseau de la société chinoise CH.com (China Mobile). Ce n’est pas un détail anodin : cela confirme que le site était utilisé comme un pion dans une infrastructure de botnet massive, pilotée depuis l’étranger.
On télécharge à chaque connexion admin $l = « https://user-images.githubusercontent.com/xxxxxxxxx/xxxxxxxxxxx-axxxxxxxxxx-xxxxxxxxxxx.jpg <- Ce n’est pas une image mais un code clé php renommé ! un appelant de payload multiple.
class-capability-manager-integration.php = backdoor + “création admin
Ce fichier est extrêmement clair :
Il charge WordPress (wp-load.php, ../wp-load.php, etc.)
Puis crée un utilisateur admin :
user : newadmin
pass : StrongPassword123!#0
email : admin@yoursite.com
Puis lui assigne le rôle administrator
C’est une porte dérobée d’élévation de privilèges. Même si le mot de passe est “fort”, il est connu (hardcodé) → donc exploitable par n’importe qui qui connaît la combine.
Donc c’est une console web + file manager + upload + edit + chmod + suppression, bref prise de contrôle totale. On fait tous sans jamais toucher au fonctionnement normal du site web, on peu faire plein de chose depuis un executable distant comme se servir du site pour attaquer en ddos, le louer pour des attaques etc…
J’ai donc signalé officiellement à GitHub l’URL incriminée pour “malware/abuse”, en expliquant qu’il s’agissait d’un payload encodé exploité pour de l’exécution de code à distance sur des sites compromis.

L’objectif est double
: contribuer au retrait de ce contenu pour limiter la propagation, et documenter l’incident dans une démarche de réponse à incident responsable.

Le nettoyage commando et la lutte contre la persistance

Une fois la menace isolée, le combat s’est déplacé vers la base de données. Le botnet disposait d’une routine de protection : dès que je supprimais les 11 comptes administrateurs frauduleux, le script tentait de dégrader mon propre compte au rang de simple « Abonné » pour me verrouiller l’accès.
J’ai dû intervenir par injections SQL directes pour verrouiller les tables et restaurer mes privilèges de force. Ce n’est qu’après cette neutralisation radicale que j’ai procédé au remplacement du cœur de WordPress et au renouvellement intégral des clés de sécurité (Salts), déconnectant instantanément tout pirate à travers le monde.

Résurrection : Un site plus fort qu’à l’origine

Nettoyer les fichiers corrompus est une victoire immédiate, mais boucher les failles est la seule garantie de paix durable. Mon objectif n’était pas seulement de rendre le site « propre », mais de le transformer en une forteresse moderne et performante.

Pour y parvenir, j’ai profité de cette intervention pour orchestrer une véritable mise à niveau structurelle :

  • Migration vers FluentForm Pro : J’ai remplacé les formulaires vulnérables par une solution premium dont j’ai offert la licence Lifetime au client. Un outil plus léger, plus sûr et désormais acquis à vie.
  • Implémentation de Cloudflare Turnstile : J’ai éradiqué le spam sans sacrifier l’expérience utilisateur. Plus de puzzles CAPTCHA irritants ; une barrière invisible mais infranchissable filtre désormais les bots en temps réel.
  • Blindage du périmètre : J’ai configuré un pare-feu actif avec des règles de filtrage agressives, bloquant définitivement les segments d’IP rattachés au botnet chinois identifié.

Conclusion : De la vulnérabilité à l’invulnérabilité

Cette intervention de 4 heures illustre parfaitement la réalité de la cybersécurité actuelle : le danger ne dort jamais et il est mondial. Un site WordPress n’est pas qu’une vitrine, c’est un actif précieux qui peut être détourné en quelques secondes par une infrastructure automatisée à l’autre bout de la planète.
Aujourd’hui, mon client ne dispose plus seulement d’un site désinfecté. Il possède une plateforme optimisée, durcie et sous haute surveillance. Le code malveillant a été éradiqué, les portes dérobées ont été soudées, et la sérénité est revenue.
Dans ce métier, la victoire ne se mesure pas seulement au nombre de fichiers supprimés, mais à la solidité des barrières que l’on construit pour que l’histoire ne se répète jamais.

Pourquoi mon antivirus n’a rien vu ?

Les malwares WordPress sont des scripts PHP, bien souvent codé en clair pour ne pas être vue. Pour un antivirus classique, c’est du texte légitime. Seule une analyse forensic des logs et du code permet de les identifier.

Le remplacement des fichiers suffit-il à nettoyer un site ?

Absolument pas. Si vous ne nettoyez pas la base de données et les scripts de persistance cachés, le site se ré-infectera en quelques secondes.

Pourquoi passer par un expert plutôt que d’utiliser un plugin de nettoyage ?

Les plugins sont des outils automatiques. Face à un botnet qui se défend et modifie vos droits admin en temps réel, seule une intervention humaine experte peut reprendre le contrôle.

Laisser un commentaire