21 octobre, 14:00 UTC. C'est le créneau qu'a choisi l'équipe sécurité de PHP pour sa release d'urgence hors cycle, un jour après la fuite des détails de CVE-2026-109618 et CVE-2026-109619, avant la divulgation coordonnée. Les deux affichent un score CVSS v4.0 de 9.2, et les flux de threat intel ont déjà baptisé la paire « php2shell ». watchTowr a reproduit la première en labo. Au moment de la fuite, personne n'avait confirmé d'exploitation massive dans la nature. Les correctifs sont sortis pour 8.2, 8.3, 8.4 et 8.5. Si ton serveur tourne en 7.4, 8.0 ou 8.1, personne en amont ne viendra t'aider.
La plupart des guides de triage que j'ai lus cette semaine, y compris l'article Medium qui m'a donné envie d'écrire, prennent ce groupe EOL au sérieux et lui proposent un plan de durcissement bien rangé : couper allow_url_fopen, définir open_basedir, aligner une longue liste dans disable_functions, bloquer les .php sous le dossier uploads dans Nginx, et verrouiller l'origine derrière les plages CIDR du WAF. Je voudrais tout ça sur n'importe quelle machine. Ce qui me gêne, c'est le discours rassurant qui va avec, l'idée que disable_functions arrête un shell avant qu'il n'atteigne le noyau. On parle d'une faille dans la gestion des requêtes du runtime lui-même. Elle est exploitable sans authentification, et elle se déclenche avant que ton routeur, ton middleware d'auth ou tes ACL ne soient chargés. Une directive php.ini est appliquée par le même code C que l'attaquant est justement en train de corrompre.
Ce n'est pas une inquiétude théorique. disable_functions traîne un long historique de contournements, plutôt embarrassant, et cet historique vient d'attaquants qui n'avaient que du PHP en espace utilisateur sous la main. Dès que quelqu'un obtient une corruption mémoire dans l'interpréteur, il a déjà dépassé la couche qui vérifie si un nom de fonction est autorisé. La liste fait échouer les payloads paresseux, ceux copiés sur un pastebin qui se contentent d'appeler system(). Elle ne fait pas grand-chose contre celui qui lit le diff sérieusement. D'après les chiffres du guide lui-même, les scanners transforment les diffs amont en sondes fonctionnelles dans les deux à six heures qui suivent un commit. Bien avant que la réunion de validation des changements pour ton cluster 7.4 n'apparaisse dans un agenda.
Voici le meilleur argument contre moi, et je vais le défendre correctement. Plein de boîtes ne peuvent pas migrer du jour au lendemain. Certaines font tourner un système de facturation de 2019 qui utilise each() à onze endroits. D'autres ont un module éditeur encodé avec ionCube qui ne se charge que sous 7.4. D'autres encore sont coincées par un contrat d'hébergement qui impose la version livrée par le panneau de contrôle. Pour elles, un durcissement en couches plus une surveillance des sockets sortants de www-data, c'est honnêtement le mieux qu'elles puissent faire ce soir, et dire que ça ne sert à rien serait cruel. Je suis d'accord avec tout ça. Ce soir, c'est la bonne décision. Je ne veux juste pas que ça devienne le plan du trimestre prochain.
Ce qui rend cet incident utile, c'est qu'il met un chiffre sur une décision que tu as déjà prise. Faire tourner 8.1 après sa fin de vie, ça a toujours été un pari : rien de critique ne sortirait dans le cœur avant ta migration. En général le pari passe et personne ne se souvient de l'avoir fait. Ce mois-ci, il n'est pas passé pour beaucoup de parcs, et la facture est arrivée sous la forme d'un week-end à grepper les racines web à la recherche de base64_decode et gzinflate, à lire des crontabs et à vérifier si /dev/shm est monté en noexec. Ajoute ces heures à l'estimation de la migration, parce que ce sont les intérêts que tu paies pour rester sur une vieille version.
Une partie peu glamour du guide mérite plus d'attention qu'elle n'en aura : l'inventaire. which -a php, un passage dans /opt/cpanel/ea-php* et /opt/plesk/php, et un docker exec dans chaque conteneur, parce que l'hôte ne les liste pas. Je parie un café que la moitié des équipes qui ont couru dans tous les sens cette semaine ont trouvé un binaire PHP dont elles ignoraient l'existence. Mon hypothèse : un worker de file d'attente sur un build différent du pool FPM, ou une image sidecar que quelqu'un a figée sur php:8.0 en 2022 avant de l'oublier. Les gens de Go adorent dire qu'un binaire statique n'a pas de runtime à patcher. Très bien, jusqu'au jour où ils doivent recompiler quarante services parce que la toolchain avait une CVE. Le graphe de dépendances de chacun est plus gros qu'il ne le croit. Une alerte sur le cœur rend simplement le nôtre visible d'un seul coup.
Donc, une fois le patch sorti et la checklist terminée : passe chaque runtime que tu fais tourner sur une branche supportée, et considère le durcissement de php.ini comme une ceinture de sécurité en plus, pas comme une excuse pour sauter la mise à jour. Avoir une version mineure de retard, c'est une dette gérable. Être sur une branche EOL, c'est parier ta sécurité sur le fait que rien de grave ne sera trouvé dans le cœur, et cette semaine, le pari a perdu.
Si tu gères un vrai parc, voilà ce que j'aimerais vraiment savoir : comment tu fais entrer les runtimes EOL dans ton budget avant qu'un incident ne t'y oblige ? Est-ce qu'un argument, une métrique ou un rapport mensuel a réellement convaincu ta direction de financer une migration depuis 7.4 chez toi ? Ou est-ce qu'il a fallu une frayeur comme php2shell à chaque fois ?




Commentaires
Pas encore de commentaire — écris le premier.
Lance la discussion
Pas de compte ni de mot de passe — saisis simplement ton adresse e-mail et nous t’envoyons un lien de connexion à usage unique. Première visite ? Tout se met en place automatiquement.
Ton évaluation sera appliquée automatiquement après ta connexion.
Vérifie ta boîte mail
Nous avons envoyé un lien de connexion à …. Ouvre-le sur cet appareil — cet onglet te connectera automatiquement.
Rien reçu ? Vérifiez le dossier spam — et marquez le message « Non spam » pour qu'il arrive directement la prochaine fois.