Un webshell, c'est quoi exactement ?
Un webshell est un fichier — le plus souvent un .php de quelques lignes — déposé sur votre hébergement, qui exécute les instructions qu'un attaquant lui envoie. Il transforme une page web en console d'administration : lister des fichiers, en téléverser, lire la base de données, envoyer des e-mails en masse.
Le terme backdoor (porte dérobée) désigne la même idée sous l'angle de la persistance : le moyen de revenir après que la faille d'origine a été refermée. C'est précisément ce qui explique les réinfections en boucle. Corriger la vulnérabilité qui a permis l'intrusion ne supprime pas la porte que l'attaquant a installée derrière.
Pourquoi le mot de passe n'y change rien
Un webshell ne passe pas par la page de connexion. Il est appelé directement par son URL. Changer les mots de passe, réinstaller un thème ou activer l'authentification à deux facteurs ne le gêne en rien : il continue de répondre tant que le fichier existe.
Les cinq signaux qui trahissent une porte dérobée
Les webshells varient énormément dans leur forme, mais très peu dans leur logique. Ce sont ces invariants que l'analyse statique recherche.
Exécution de code reçu dans la requête
Le fichier prend une valeur envoyée par l'attaquant ($_POST, $_GET, $_COOKIE, un en-tête HTTP) et l'exécute. C'est la définition même d'un webshell : le code n'est pas dans le fichier, il arrive à chaque visite.
Décodage en cascade
base64_decode, gzinflate, str_rot13, souvent imbriqués sur plusieurs niveaux et sur une seule ligne de plusieurs milliers de caractères. Le but est d'empêcher la lecture, pas de gagner de la place.
Appel de fonction dynamique
Le nom de la fonction à exécuter est reconstruit à l'exécution, ou lu directement dans la requête. Aucun code applicatif légitime n'a besoin de laisser un visiteur choisir la fonction appelée.
Filtrage par en-tête ou par adresse IP
La porte dérobée ne s'active que pour son propriétaire — un User-Agent précis, un cookie, une IP. Pour tous les autres visiteurs, y compris les scanners qui chargent la page, le fichier ne fait rien.
Date de modification incohérente
Un fichier daté du jour dans un dossier qui n'a pas bougé depuis deux ans. Indice utile — mais la date est falsifiable en une ligne, elle ne prouve rien à elle seule.
Aucun de ces signaux pris isolément ne prouve une infection : des extensions légitimes utilisent du code encodé, et certains constructeurs de pages appellent des fonctions de façon dynamique. C'est la combinaison — du code reçu de la requête, puis décodé, puis exécuté — qui ne s'explique pas autrement.
Où elles se cachent
| Emplacement | Pourquoi là |
|---|---|
| wp-content/uploads/ | Le dossier est accessible en écriture par WordPress lui-même, il contient des milliers de fichiers, et personne ne va le lire. Un .php y est toujours anormal : rien dans WordPress n'y dépose de PHP. |
| wp-content/plugins/<extension>/ | Un fichier ajouté dans une extension légitime passe pour un fichier de l'extension. La comparaison avec la version officielle du dépôt WordPress.org est le seul moyen fiable de le repérer. |
| wp-includes/ | Le dossier le plus intimidant du core : beaucoup d'administrateurs n'osent pas y toucher. Or son contenu est publié et vérifiable fichier par fichier. |
| Racine du site | Sous un nom qui imite le core — wp-signin.php, wp-blog.php, wp-conf.php. Aucun de ces fichiers n'existe dans WordPress. |
| Table wp_options / tâches planifiées | La porte dérobée n'est pas un fichier : le code est stocké en base et réinjecté à chaque chargement. Un nettoyage limité aux fichiers la laisse intacte. |
Une règle simple couvre déjà beaucoup de cas : aucun fichier .php n'a de raison d'exister dans wp-content/uploads/. Si vous en trouvez un, examinez-le avant toute autre chose.
Trois méthodes de détection, et ce que chacune rate
1. Comparaison avec les fichiers officiels
WordPress.org publie l'empreinte de chaque fichier du core pour chaque version. Toute divergence est détectable avec certitude, sans interprétation. Sa limite : elle ne couvre que le core. Un fichier ajouté dans uploads, ou une extension modifiée, échappe entièrement à cette méthode.
2. Règles de signature (YARA)
On lit les octets du fichier et on cherche les combinaisons décrites plus haut. C'est la méthode la plus efficace sur les webshells, car leur logique varie peu. Sa limite : un shell entièrement chiffré (AES, XOR avec clé) ne présente plus aucun motif reconnaissable. Aucune signature statique ne peut le voir.
3. Analyse depuis l'extérieur du site
Un outil qui s'exécute à l'intérieur de WordPress travaille dans l'environnement qu'il est censé auditer. Déporter l'analyse évite ce problème et ne consomme pas les ressources de votre hébergement. Sa limite : la collecte des fichiers transite quand même par le site. C'est l'analyse qui est externe, pas la lecture.
Nos chiffres, angle mort compris
Peu d'éditeurs publient leur taux de détection. Voici les nôtres, mesurés sur des corpus de malwares réels — y compris celui qui nous dessert.
de rappel sur 381 webshells PHP réels : 365 détectés.
sur du malware PHP générique chiffré : 50 sur 102. C'est notre angle mort, et celui de toute analyse statique.
faux positif observé sur 1 285 fichiers du core WordPress et 56 motifs pièges. Les extensions de type gestionnaire de fichiers n'ont pas été testées.
Le chiffre de 95,8 % vaut pour les webshells — la menace la plus courante sur WordPress. Ce n'est pas un taux de détection universel, et nous ne le présenterons jamais comme tel.
Le vrai piège : la fausse alerte
Chercher agressivement des webshells produit un effet secondaire connu : des extensions parfaitement légitimes se font signaler. Les gestionnaires de fichiers, les constructeurs de pages et certains frameworks utilisent naturellement du code encodé ou des appels dynamiques.
Un outil qui affiche « site infecté » pour ce genre de motif vous fait supprimer un fichier sain — et casse le site. C'est pourquoi nous classons chaque résultat en trois niveaux plutôt qu'en oui/non : menace confirmée, à vérifier, informatif. Tant qu'aucune menace n'est confirmée, le score reste plafonné à 15/100. Un indice n'est pas une infection.
Si vous en trouvez une
- Ne supprimez rien tout de suite. Le fichier est votre principale preuve pour comprendre par où l'attaquant est entré.
- Sauvegardez fichiers et base de données avant toute intervention, même dans un état compromis.
- Cherchez les autres. Une porte dérobée est rarement seule : l'attaquant en dépose plusieurs, précisément pour survivre à un nettoyage partiel.
- Identifiez le point d'entrée — extension vulnérable, mot de passe FTP compromis, thème téléchargé hors dépôt officiel. Sans cela, la réinfection est une question de jours.
- Remplacez plutôt que réparer : réinstallez le core et les extensions depuis les sources officielles, au lieu de tenter de désinfecter un fichier ligne par ligne.
Le déroulé complet figure dans notre guide Comment nettoyer un WordPress hacké. Et si vous n'êtes pas encore certain d'être infecté, commencez par les signes d'une infection WordPress.
Voir à quoi ressemble un vrai rapport
Nous publions un rapport de scan réel — 9 411 fichiers analysés, aucune menace confirmée — consultable sans créer de compte. Vous y verrez comment chaque élément est classé, et pourquoi un fichier signalé n'est pas forcément une infection.
Voir un rapport réel →Nous détectons et nous vous disons quoi faire. Le nettoyage reste à votre charge — nous ne le réalisons pas à votre place.