« sh -c /usr/sbin/sendmail -t -i », propriétaire www-data. J'ai trouvé cette ligne dans une liste de processus la semaine dernière et j'ai passé quatre bonnes minutes le cœur battant avant de me rappeler que la fonction mail() de PHP fait exactement ça, à chaque fois, par conception. Cette fausse alerte, au fond, c'est toute la chronique. Depuis le 21 octobre, on patche tous CVE-2026-109618 et CVE-2026-109619, le duo que tout le monde appelle désormais php2shell, et les retours de la communauté sur leur détection se heurtent toujours au même mur : l'exploit est un bug mémoire qui se déclenche avant même que ton code applicatif tourne, donc tes logs ne montrent rien. Tout ce que tu peux attraper, c'est la suite. Et la suite ne ressort que si ton utilisateur web est ennuyeux en temps normal.

Mon argument porte donc sur l'architecture, pas sur les règles d'alerte. Si www-data lance régulièrement des shells, écrit des fichiers .php dans le document root et exécute des tâches cron, aucune règle de détection, qui que soit son auteur, ne distinguera un attaquant de ton mardi ordinaire. Une règle n'est jamais plus fine que ta base de référence n'est calme. Un utilisateur web qui n'exécute jamais rien et n'écrit jamais de code te donne un signal auquel tu peux vraiment te fier. Un utilisateur web qui fait les deux dès qu'un plugin en a envie te donne un tableau de bord rempli d'alertes de niveau 8 que tout le monde a appris à ignorer dès le jeudi.

Rappelle-toi à quel point celle-ci est grave. CVSS v4.0 9.2, sans authentification, et elle touche PHP-FPM, mod_php, php-cgi, FrankenPHP et LiteSpeed sans distinction, mod_php étant le pire cas puisque l'attaquant est entré avant même que ton routeur ne se charge. Les versions corrigées sont 8.5.12, 8.4.27, 8.3.36 et 8.2.35. Tout ce qui tourne en 8.1 ou antérieur n'a aucun correctif officiel, et les utilisateurs de Debian bullseye coincés sur PHP 7.4 n'ont rien eu non plus. À la publication de l'avis, le flux de vulnérabilités de Wazuh ne connaissait encore aucune des deux CVE, CISA KEV ne les avait pas listées, et la seule preuve de concept en circulation n'était pas vérifiée, peut-être même piégée. Pendant quelques jours, beaucoup d'équipes se sont défendues contre une menace que leurs scanners ne savaient même pas nommer.

L'objection la plus solide mérite une réponse franche, parce qu'elle est juste. Les vraies applications PHP font ces choses exprès. WordPress se met à jour en écrivant du PHP dans sa propre arborescence. La moitié des CMS que j'ai maintenus exécutent leurs tâches planifiées sous l'utilisateur web, parce que c'était la solution de facilité en 2014. La fonction mail() passe par un shell. Demander à une petite agence avec quarante sites clients de reconstruire tout ça en pleine urgence, c'est de la science-fiction, et je ne vais pas prétendre le contraire. Le camp de la détection d'abord n'a pas tort non plus : on ne refait pas l'architecture sous le feu, alors on surveille ce qu'on a et on accepte le bruit.

Je penche quand même de l'autre côté, et voici pourquoi. Chacune de ces habitudes peut être abandonnée pour un prix connu et limité. Envoie tes mails en SMTP via une bibliothèque, et mail() ne forkera plus jamais. Lance les mises à jour depuis un utilisateur de déploiement dans ton pipeline, et rends le document root accessible en lecture seule au processus qui le sert. Déplace le cron sur son propre compte. Rien de tout ça n'est exotique, et une fois que c'est fait, un échantillon de la liste des processus ou un outil de surveillance d'intégrité des fichiers passe d'un indice bruyant à une alarme quasi certaine. Un échantillonnage toutes les 60 secondes ratera toujours un curl qui vit deux secondes. Mais sur un compte calme, un seul résultat suffit, parce que rien ne devrait s'y trouver.

Encore un point qui n'a rien à voir avec la détection astucieuse : un paquet mis à jour ne corrige pas les workers php-fpm déjà en cours d'exécution. J'ai vu deux serveurs ce mois-ci en 8.3.36 selon apt et toujours sur le binaire vulnérable selon la réalité, parce que personne n'avait redémarré le pool. Honnêtement, c'est le mode d'échec le plus PHP qui soit : notre modèle shared-nothing pardonne presque tout, sauf le processus maître qui tourne depuis août. Redémarre-le. Puis va vérifier que tu l'as vraiment fait.

Pour les retardataires entre 7.4 et 8.1, la démarche honnête consiste à les retirer de l'internet public, pas à bâtir de la surveillance autour en appelant ça de la couverture. Surveiller une porte que tu sais impossible à verrouiller, ça sert une semaine, au mieux. Au-delà, c'est juste un plan pour découvrir la compromission un peu plus tôt.

Alors voici ce que j'aimerais vraiment savoir, parce que je soupçonne que les réponses se partagent entre agences et éditeurs de produits : sur tes serveurs de production aujourd'hui, l'utilisateur qui sert PHP peut-il écrire dans le répertoire qu'il sert ? Et si oui, quelle est la fonctionnalité que tu perdrais en lui retirant ce droit, et vaut-elle un angle mort de la taille de php2shell ?