PHP2Shell : comment savoir si votre site PHP a été attaqué
Les commandes pour chercher des traces sur un serveur Debian avec nginx et PHP-FPM, et quoi faire si vous en trouvez
Image générée par IA (art. 50 AI Act)
Analyse 2LKATIME
Vous avez mis PHP à jour ? Il reste une question : quelqu'un est-il passé avant ? Les premières tentatives datent du 17 octobre, quatre jours avant le correctif. Ce guide donne les commandes pour chercher les traces sur un serveur Debian avec nginx et PHP-FPM, la configuration la plus répandue pour WordPress. Il complète notre article sur les failles PHP.
Un hébergement mutualisé ? Posez la question à l'hébergeur
Vous n'avez pas accès aux journaux système. Demandez à votre hébergeur s'il a mis PHP à jour, à quelle date, et s'il a cherché des traces d'exploitation sur sa plateforme.
Le correctif ferme la porte. Il ne dit pas si quelqu'un est déjà entré. Tant que PHP n'était pas corrigé, tout serveur exposé était à portée d'un scan, et les attaques observées couvrent plusieurs jours avant et après la publication. À ce jour, les sources que nous avons lues ne rapportent aucune compromission confirmée d'un serveur précis. Cela ne prouve rien pour le vôtre.
Les chercheurs de Datadog, qui ont reproduit l'exploit, distinguent trois endroits où chercher : les requêtes reçues, le journal d'erreurs de PHP et les processus lancés par le serveur web. Aucun signal ne suffit seul. Il faut les recouper.
1. Où en est l'exploitation
17 oct.
Première tentative signalée par Amazon, avant le correctif
21 oct.
Correctif PHP, puis des millions de tentatives selon Cloudflare
26 oct.
Ajout au catalogue CISA des failles exploitées (watchTowr)
Aucune
Compromission d'un serveur précis confirmée dans les sources lues
Amazon a relevé une tentative dès le 17 octobre. Après la publication du 21, Cloudflare dit être passé de dizaines de milliers de tentatives en 45 minutes à des millions le lendemain matin, et voir les attaquants adapter leurs requêtes pour contourner ses règles. Sophos et Arctic Wolf décrivent des essais d'installation d'une variante du botnet Mirai. Wordfence et d'autres rapportent surtout du scan et des sondages. Selon The Hacker News, les chercheurs jugent un exploit fiable plus difficile à construire qu'annoncé.
Ce dernier point ne doit pas rassurer. Datadog a produit un exploit fonctionnel contre mod_php, avec une simple requête sans authentification, et la CISA a inscrit la faille à son catalogue des vulnérabilités exploitées. La capacité existe, les attaquants testent, et ils s'améliorent.
La période à examiner court du 17 octobre jusqu'à l'heure où vous avez appliqué le correctif et redémarré PHP-FPM. Pour un serveur mis à jour le 21 au soir, cela fait environ quatre jours et demi.
2. Ce que laisse une attaque
Une attaque réussie ne fait pas forcément planter le serveur. Datadog note que la requête peut répondre normalement, avec un code 200. Trois familles de signaux existent.
1. Les requêtes reçues
Des envois de fichiers anormaux : des centaines de parties dans une même requête, un champ de plusieurs mégaoctets, des noms de champs imbriqués à répétition, ou les champs PHPSESSID et PHP_SESSION_UPLOAD_PROGRESS dans une application qui ne s'en sert pas. Datadog signale aussi de gros formulaires classiques dont un seul nom de champ pèse plusieurs mégaoctets. Côté réponse, un cookie PHPSESSID anormalement long peut trahir une lecture de mémoire.
2. Le journal d'erreurs de PHP
Le message « Allowed memory size ... exhausted » suivi de « in Unknown on line 0 » indique un échec survenu avant l'exécution du moindre script. Quelques erreurs de ce type sur un worker, puis le calme, peuvent suffire à une attaque complète. Un worker qui plante (« exited on signal 11 ») est un autre signe, car l'exploit rate parfois l'adresse mémoire visée.
3. Les processus du serveur web
C'est la preuve la plus directe : un shell (sh, bash) lancé par PHP-FPM ou par nginx, qui ouvre ensuite une connexion sortante. Datadog précise que l'exploit n'a pas besoin de faire planter le worker et que la requête peut répondre normalement.
Une limite à connaître : le journal d'accès par défaut de nginx n'enregistre ni le corps des requêtes ni leur type de contenu. Vous ne verrez donc pas les champs d'envoi de fichiers. Vous verrez les requêtes POST, leur cible, et les erreurs 500 ou 502 qui les accompagnent.
3. Les commandes à lancer
Les chemins ci-dessous correspondent à Debian 12, nginx et PHP 8.2. Adaptez le numéro de version et le dossier du site. Toutes ces commandes lisent sans rien modifier.
Le journal d'erreurs de PHP-FPM
sudo zgrep -hE "Unknown on line 0|Allowed memory size|exited on signal|SIGSEGV" /var/log/php8.2-fpm.log*
Un résultat vide est bon signe. Quelques lignes datées du 17 au 21 octobre, surtout avec « Unknown on line 0 », méritent d'être regardées de près.
Les erreurs 500 et 502, jour par jour
sudo zcat -f /var/log/nginx/access.log* | awk '$9 ~ /^(500|502)$/ {print substr($4,2,11)}' | sort | uniq -c
Un pic inhabituel sur un jour, sans lien avec une mise à jour ou une panne connue, est un indice de plus.
Les cibles des requêtes POST
sudo zcat -f /var/log/nginx/access.log* | grep '"POST ' | awk '{print $7}' | sort | uniq -c | sort -rn | head -20
Sur un WordPress, vous attendez surtout wp-login.php (ou votre adresse personnalisée), admin-ajax.php et wp-cron.php. Un POST sur la racine ou sur un fichier que vous ne reconnaissez pas est à noter.
Les processus et les connexions
sudo ps -u www-data -o pid,ppid,etime,cmd --forest
sudo ss -tnp | grep -E "php-fpm|www-data"
Les processus attendus sont php-fpm et les workers nginx. Un sh, un bash, un curl, un wget, un python ou un processus inconnu sous www-data justifie une enquête immédiate. Les connexions normales de PHP-FPM vont vers la base de données et vers les services dont dépend votre site ; une connexion vers une adresse inconnue sur un port inhabituel ne l'est pas.
Les fichiers récents
sudo find /var/www/html -name "*.php" -newermt "2026-10-17" -not -path "*/wp-content/plugins/*" -not -path "*/wp-content/cache/*" -ls
sudo find /var/www/html -path "*/uploads/*" -name "*.php" -ls
sudo find /tmp /var/tmp /dev/shm -user www-data -newermt "2026-10-17" -ls
sudo crontab -u www-data -l
Aucun fichier PHP ne devrait traîner dans le dossier des téléversements. Un fichier récent hors plugins, dans le cœur de WordPress ou dans un dossier temporaire, est suspect. Une mise à jour de WordPress ou d'un thème peut en créer légitimement : comparez avec vos dates de mise à jour. « no crontab for www-data » est la réponse normale.
WordPress lui-même
sudo -u www-data wp core verify-checksums --path=/var/www/html/wordpress
sudo -u www-data wp plugin verify-checksums --all --path=/var/www/html/wordpress
sudo -u www-data wp user list --role=administrator --fields=ID,user_login,user_registered --path=/var/www/html/wordpress
Ces commandes demandent WP-CLI. Les deux premières comparent vos fichiers aux versions officielles, la troisième liste les administrateurs : tout compte que vous ne reconnaissez pas est un signal fort.
4. Si vous trouvez quelque chose
Un seul indice isolé ne prouve pas une intrusion, et un résultat vide ne prouve pas le contraire. Si plusieurs signaux concordent, par exemple une erreur « Unknown on line 0 » suivie d'un fichier PHP inconnu, traitez-le comme un incident.
1. Isoler
Coupez l'accès public du site (maintenance, ou règle nginx qui renvoie 503) avant de toucher quoi que ce soit.
2. Copier les journaux
Copiez /var/log/nginx et les journaux PHP-FPM hors du serveur avant la prochaine rotation. Sur beaucoup d'installations, nginx ne garde que 14 jours : la fenêtre du 17 octobre est à la limite.
3. Restaurer sur un PHP corrigé
Repartez d'une sauvegarde antérieure au 17 octobre, sur un serveur déjà mis à jour. Ne remettez pas en ligne les fichiers du serveur touché sans les comparer.
4. Changer les secrets
Mots de passe des administrateurs, clés de sécurité de wp-config.php, mot de passe de la base, clés d'API, jetons de services tiers. Une lecture de mémoire a pu en exposer.
5. Signaler
Prévenez la CNIL sous 72 heures si des données personnelles sont concernées. Vous pouvez aussi déposer plainte et demander de l'aide à cybermalveillance.gouv.fr.
5. Réduire le risque pour la suite
Gardez PHP à jour, et gardez session.upload_progress.enabled=0 : le projet PHP le recommande aussi contre une troisième faille signalée le 23 octobre, CVE-2026-115560, qui n'a pas encore de correctif ni d'exploitation connue. Si vous n'utilisez pas l'envoi de fichiers, refusez les requêtes multipart en amont, au niveau de nginx ou du pare-feu applicatif. Cloudflare a activé des règles par défaut, ce qui aide sans remplacer la mise à jour.
Envoyez aussi vos journaux hors du serveur. Un attaquant qui exécute des commandes peut effacer les traces locales. Et planifiez la migration hors de PHP 8.2, qui sort du support le 31 décembre 2026.
6. Conformité
Une intrusion qui touche des données personnelles est une violation au sens du RGPD : notification à la CNIL sous 72 heures si le risque pour les personnes est avéré, et inscription au registre des violations dans tous les cas. Pour les entités soumises à NIS2, un incident significatif suppose une alerte précoce sous 24 heures. Dans les deux cas, les journaux que vous aurez copiés vous serviront de preuve.
7. Ce que 2LKATIME recommande
Si vous ne savez pas lire ces résultats, ou si l'un d'eux vous inquiète, ne tardez pas : la fenêtre de journaux s'étrécit chaque jour. Nos audits cybersécurité incluent une analyse de compromission et une revue de configuration du serveur.
Les structures de Paris, de Lyon ou de Bordeaux trouveront les formules sur nos pages tarifs. L'analyse se fait aussi à distance partout en France.
FAQ - Détecter une attaque PHP2Shell
Mon site est à jour : suis-je tranquille ?
Pas tout à fait. La mise à jour ferme la porte, elle ne dit pas si quelqu'un est entré avant. Les premières tentatives datent du 17 octobre, quatre jours avant le correctif. Vérifiez la période entre cette date et l'heure de votre mise à jour, et gardez les journaux de cette période.
Que cherchent les attaquants avec cette faille ?
Selon Sophos et Arctic Wolf, des essais d'installation d'une variante du botnet Mirai, qui ont échoué jusqu'ici. L'attaque peut aussi lire la mémoire d'un worker PHP, qui peut contenir des mots de passe, des jetons ou des clés d'API d'autres requêtes, sans exécuter de code. D'où l'intérêt de changer les secrets en cas de doute.
Les journaux de nginx suffisent-ils pour détecter une attaque ?
Non. Le journal d'accès par défaut n'enregistre ni le corps des requêtes ni leur type de contenu : vous ne voyez pas les champs d'envoi de fichiers. Croisez-le avec le journal d'erreurs de PHP-FPM, la liste des processus lancés par www-data et les fichiers récents du site.
Dois-je tout restaurer par précaution ?
Pas si vous ne trouvez aucun indice et que PHP est à jour. Changer les clés de sécurité de wp-config.php et les mots de passe coûte peu et invalide les sessions ouvertes. Si vous trouvez un fichier PHP inconnu, un shell lancé par le serveur web ou un compte administrateur inconnu, restaurez une sauvegarde saine sur un PHP corrigé.
Faut-il prévenir la CNIL ?
Seulement si une violation de données personnelles est avérée ou probable : la notification se fait sous 72 heures. Même sans notification, le RGPD demande de consigner l'incident dans un registre des violations, avec les faits et les mesures prises.
Sources
Votre site a-t-il été touché entre le 17 et le 21 octobre ?
2LKATIME analyse vos journaux, vos fichiers et la configuration de votre serveur, puis vous remet un rapport clair avec les actions à mener.