WPFormationWordPress, rien que du WordPress
Formation WordPress + IA
IA & Claude Code · Qualiopi · OPCO
Je me forme
Illustration PHP2Shell : le numéro de version PHP ne prouve rien, la preuve est la commande grep du marqueur dans le binaire
Sécurité WordPress

PHP2Shell : le numéro de version PHP ne prouve rien

Par Fabrice Ducarme··15 min de lecture
Résumé de l'article

Le 21 octobre 2026, PHP a corrigé deux failles critiques (PHP2Shell, CVE-2026-109618 et 109619). Plusieurs hébergeurs ont repris le correctif sous un numéro de version inchangé : le numéro affiché ne prouve donc rien. Sur PHP 8.2 à 8.5, la preuve la plus sûre est la chaîne du correctif dans le binaire qui sert le site.

Pas le temps ? Faites-le analyser par l'IA

Vous me lisez souvent ? Dites-le à Google

J'ajoute WPFormation à mes sources

8.4.26. Le même numéro qu’avant l’alerte, affiché par un serveur que je venais pourtant de corriger. Et l’inverse existe : un serveur qui annonce 8.4.27 et tourne encore avec l’ancien moteur. Du soir du 21 octobre 2026 au petit matin, j’ai passé plusieurs heures à comprendre une chose simple : face à la faille baptisée PHP2Shell, le numéro de version de PHP ne prouve rien. Ni dans un sens, ni dans l’autre.

Je forme à WordPress depuis 2012 et je gère la maintenance de sites chez plusieurs hébergeurs. Ce jour-là, j’ai corrigé mes serveurs avant que la plupart des messages officiels ne sortent, puis j’ai cherché comment vérifier, pour de vrai, qu’un site était protégé. Voici ce que j’ai fait, ce que j’ai mesuré, et la méthode de vérification qui manquait aux messages des hébergeurs.

PHP2Shell, qu’est-ce que c’est exactement ?

PHP2Shell, ce sont deux failles critiques de PHP lui-même, corrigées le 21 octobre 2026 : CVE-2026-109618 et CVE-2026-109619, notées 9.2 sur 10 chacune. Elles permettent l’exécution de code à distance sans authentification, avant même le moindre code de votre site. Aucune extension WordPress ne vous en protège : la faille est sous WordPress, dans le moteur. Les failles d’extensions que l’IA déniche désormais à la chaîne ne sont plus seules : cette fois, c’est dans le socle que l’IA a trouvé la brèche, sous toutes les extensions.

Le nom "PHP2Shell" ne vient pas de l’équipe PHP. C’est le nom qu’ont donné des chercheurs (Wiz Research, OpenAI Codex Security et Calif) à leur script de démonstration, celui qui prouvait l’exécution de code sur WordPress, Drupal et Joomla. Leur page le dit noir sur blanc : "php2shell is the name we gave the combined exploit script". Un détail, mais qui compte quand on fait de la veille : vous ne trouverez ce mot ni dans l’avis de php.net, ni dans les notes de version.

Les versions qui corrigent sont PHP 8.5.12, 8.4.27, 8.3.36 et 8.2.35. L’avis officiel est clair sur qui court le plus de risque : "all PHP installations serving web requests", avec le risque le plus élevé pour Apache en mod_php. Et une phrase qui a cassé mon plan du matin : "Do not rely on ini_set() or FPM .user.ini". J’y reviens.

Pour les versions plus anciennes, PHP 8.1 et antérieures ne reçoivent plus de correctif du projet PHP. Des "rétroportages de source minimaux" ont été fournis pour 7.4, 8.0 et 8.1, mais c’est à chaque distribution ou hébergeur de les intégrer, sans garantie. Retenez juste : si vous tournez encore en PHP 7.x ou 8.0, vous n’êtes pas dans le périmètre normal des correctifs. Raison de plus pour migrer, ce que j’avais déjà développé dans mon guide sur la migration vers WordPress 7 et PHP 8.

Le 21 octobre, heure par heure, sur mes serveurs

L’alerte m’est arrivée tôt, par un relai, avant même la publication officielle. php.net avait annoncé la veille deux failles critiques pour le 21 octobre à 14 h UTC (16 h à Paris), sans donner ni les numéros, ni les atténuations. À 7 h, j’ai posé le seul réglage qui circulait, session.upload_progress.enabled = Off, et j’ai pris des instantanés complets de mes serveurs avant toute intervention. J’ai aussi fait une photo de référence de mes sites importants : fichiers et empreintes, vers 14 h, avant la fenêtre dangereuse.

À 15 h 36, j’ai lu l’avis officiel. Mauvaise nouvelle : mon réglage du matin ne couvrait qu’une des deux failles, et seulement s’il était dans la configuration du serveur, pas dans un fichier .user.ini. Or sur les hébergements mutualisés, je n’avais que le .user.ini. À 15 h 58, aucune version corrigée disponible chez mes fournisseurs habituels. Patchstack signalait déjà des "multiple active exploitation incidents" dès 7 h 34 UTC, et Sansec prédisait alors des attaques massives dans les quinze minutes suivant la publication (prévision revue à la baisse le 22 octobre). Il fallait agir, pas attendre.

À 16 h 27, décision : fabriquer PHP 8.4.27 moi-même, à partir des sources officielles de php.net, empreinte contrôlée. La compilation complète produisait huit variantes, l’une après l’autre : près d’une heure. À 16 h 57, verdict : "beaucoup trop lent". Mes sites ne passent que par un seul composant, php-fpm, et les attaques démontrées exploitent la lecture des requêtes et le module de session, compilés dans ce binaire. J’ai donc compilé le seul php-fpm ; les extensions partagées, que le correctif retouche aussi, ont suivi le soir avec les paquets complets.

À 16 h 58, nouvel instantané. À 17 h 02, contrôle : le nouveau binaire chargeait les mêmes modules que l’ancien, ligne pour ligne, sans le moindre avertissement. À 17 h 02 et 51 secondes, j’ai échangé le binaire, en gardant l’ancien de côté pour un retour arrière en deux secondes. Redémarrage : 2 secondes. À 17 h 13, le moteur PHP de tous mes sites exposés était corrigé, une heure quarante après la publication des avis.

Un numéro qui ment déjà : mon contrôle interne affichait encore "8.4.26" après l’échange. Normal : il lisait le PHP en ligne de commande, celui que je n’avais pas touché parce qu’aucune requête web ne passe par lui. Le binaire qui sert vraiment les pages, lui, était bien corrigé. Première alerte sur le piège du numéro.

Le soir, la fibre du bureau est tombée en panne (j’étais en déplacement une partie de la journée) : bascule sur le secours 4G, hors de ma liste d’accès habituelle, bricolage de tunnels pour garder la main. À 19 h 56, mes paquets complets étaient posés. À 19 h 58, les binaires officiels de mon serveur LiteSpeed étaient enfin publiés et installés. Le dépôt Sury, lui, a publié vers 20 h (18 h UTC), mais son serveur de fichiers croulait sous l’afflux mondial et répondait en erreur : posé seulement à 23 h 31. Une faille critique, ça ne se corrige pas en claquant des doigts, même quand on sait quoi faire.

Pourquoi le numéro affiché par phpinfo() ne prouve rien ?

Parce que beaucoup d’hébergeurs et de distributions ont repris le correctif dans leur paquet sans changer le numéro de version. On appelle ça un rétroportage : la correction est intégrée, mais l’étiquette reste l’ancienne. Résultat, un phpinfo() ou un info.php peut afficher 8.4.26 sur un serveur parfaitement protégé. À l’inverse, la commande php -v ou le panneau de l’hébergeur peuvent annoncer 8.4.27 alors que les processus PHP n’ont pas redémarré et servent encore l’ancien moteur en mémoire.

Les hébergeurs l’ont écrit eux-mêmes. CloudLinux, dont les paquets alt-php équipent de nombreux hébergeurs mutualisés, O2switch compris : "These packages contain the fix for both CVEs, even though the PHP version number is lower". Leur exemple, le paquet ea-php84 corrigé : 8.4.26-2, pas 8.4.27. CloudLinux a publié ensuite des paquets aux numéros de php.net (alt-php84 en 8.4.27-1, par exemple). O2switch l’a dit à ses clients le 22 octobre : "pour PHP 8.3, la version affichée restera 8.3.35 (package 8.3.35-6 intégrant le correctif)". Côté distributions, Ubuntu a livré le correctif dans un paquet numéroté 8.3.6, et AlmaLinux dans du php-8.3.33.

Le piège guette aussi ceux qui suivent les conseils automatiques. Le 23 octobre encore, le Mode IA de Google répondait à qui lui demandait si son hébergeur avait corrigé : créer un fichier info.php et comparer le numéro aux versions minimales corrigées. Suivi à la lettre, ce conseil déclare "vulnérable" un serveur protégé par rétroportage. Mettre à jour une application ne met pas à jour le moteur PHP en dessous, et le nouveau moteur ne sert vraiment qu’après avoir relancé Apache, php-fpm et tous les processus PHP longue durée.

Plusieurs hébergeurs conseillent de regarder la "Build Date" du binaire. C’est un indice utile, cohérent sur tout ce que j’ai mesuré, mais il dit quand le binaire a été compilé, pas avec quel code. Un indice, pas une preuve.

Comment vérifier, pour de vrai, que le correctif est là ?

En cherchant la trace du correctif directement dans le binaire qui sert le site. Le correctif officiel (commit php-src 506e87fa7d, "Avoid state corruption via bailout", qui cite les deux avis GHSA) ajoute dans le code un message d’erreur précis : Hard memory limit of … exhausted. Cette chaîne de caractères est absente des versions non corrigées et présente dans les versions corrigées. Elle sert de marqueur, lisible sans exécuter quoi que ce soit.

La commande, sur le binaire qui sert réellement vos pages (le php-fpm du site, pas le PHP en ligne de commande) :

grep -c -a "Hard memory limit of" /chemin/vers/le/binaire-php

Le résultat est 0 sur une version non corrigée, 1 ou plus sur une version corrigée. Pour être sûr de viser le bon fichier, celui du processus qui tourne vraiment, passez par le lien /proc/<pid>/exe du maître php-fpm. S’il porte la mention "(deleted)", c’est que le paquet a été mis à jour mais que le service n’a pas redémarré, et vous servez encore l’ancien moteur.

J’ai voulu être certain que ce marqueur tenait la route, alors j’ai fait une épreuve sur des binaires connus. Verdict : 1 dans mes PHP 8.4.27 et 8.2.35 fraîchement posés, 0 dans les 8.4.26 et 8.3.35 d’origine que j’avais gardés de côté. Le marqueur dit juste.

Pour que vous puissiez le refaire sans toucher à un serveur, voici une démonstration reproductible menée le 23 octobre sur les binaires Windows officiels de PHP. J’ai téléchargé les archives 8.4.26 et 8.4.27 depuis le site officiel et vérifié l’empreinte SHA-256 de la 8.4.27 contre la somme publiée. Puis j’ai extrait la bibliothèque php8.dll de chacune sans rien exécuter et compté la chaîne :

grep -c -a "Hard memory limit of" 8.4.26/php8.dll   # 0
grep -c -a "Hard memory limit of" 8.4.27/php8.dll   # 1

Sous Windows sans grep, la commande PowerShell Select-String -SimpleMatch donne le même résultat : 0 contre 1. La chaîne complète dans le binaire corrigé est "Hard memory limit of %zu bytes exhausted". Deux fichiers, une recherche de texte, aucune exécution : c’est à la portée de n’importe qui.

Schéma : chercher la chaîne Hard memory limit of dans le binaire php-fpm, 0 ou 1 selon la version de PHP
Le marqueur dans le binaire : 1 si le correctif est là, sur PHP 8.2 à 8.5.

La limite du marqueur sur les vieilles branches : pour PHP 7.4, 8.0 et 8.1, les rétroportages de source sont minimaux et n’ajoutent pas cette chaîne (vérifié sur la branche 8.1). Sur ces branches, l’absence du marqueur ne prouve donc pas que vous êtes vulnérable : elle ne permet pas de conclure. La bonne démarche est alors de demander au fournisseur, journal du paquet à l’appui.

Si vous n’avez pas accès au serveur en ligne de commande, il reste une méthode que les hébergeurs eux-mêmes recommandent : le journal du paquet. Sur un système à base de RPM, rpm -q --changelog sur le paquet PHP montre si la correction des deux CVE y est inscrite, numéro de version ou pas. C’est la preuve que CloudLinux met en avant, précisément parce que son numéro reste inférieur. Avec une exception, qu’il signale lui-même : ses paquets PHP natifs 8.2 et 8.3 (ceux du système, pas alt-php ni ea-php) ne citent pas les CVE dans leur journal. Pour eux, c’est le numéro qui fait foi : 8.2.35 ou 8.3.36 au moins, avec rpm -q php-cli.

O2switch, Infomaniak et les autres : le geste avant le message

Deux hébergeurs que je côtoie au quotidien ont corrigé vite, dans la nuit, sous l’ancien numéro. O2switch a remplacé ses binaires alt-php dès le 21 octobre (date de fabrication entre 10 h 48 et 13 h 31 selon la branche), et son message clair aux clients n’est arrivé que le lendemain, le 22 octobre à 9 h 33 : "Attention cependant à la numérotation des versions installées sur nos serveurs !". Infomaniak a désactivé le réglage à risque dès 16 h 53 le 21 et déployé ses mises à jour dans la foulée. Le 22 à 7 h 42, l’hébergeur a expliqué que "les numéros de version PHP restent inchangés, mais les correctifs de sécurité ont bien été appliqués". Dans les deux cas, le geste technique a précédé le message. Je le dis sans reproche : corriger d’abord, communiquer ensuite, c’est le bon ordre.

Il a manqué, à mon sens, juste un message plus tôt et une méthode de vérification donnée au client. Quand j’ai fondé puis dirigé WPServeur, j’ai appris que dans une urgence pareille, la moitié du travail est technique, l’autre moitié est de permettre au client de constater lui-même que c’est réglé. Un numéro de version qui ne bouge pas, sans explication, angoisse le client, et à juste titre.

Voici ce que les principaux acteurs ont annoncé publiquement, avec l’heure qu’ils affichent (UTC quand leur page le précise) et le point à retenir. Les liens pointent vers leur page officielle.

ActeurCe qu’il a annoncéRepère
O2switchCorrectifs CloudLinux intégrés sans changer le numéro ; réglage à risque désactivé par défautMessage le 22/10 à 9 h 33, correction la veille
InfomaniakBuilds recompilés, numéros inchangés ; versions officielles sur le mutualisé puis les Serveurs Cloud managés le 23/10Réglage désactivé à 16 h 53 le 21/10
OVHcloudContournement à 8 h UTC ; PHP 7.4 à 8.5 corrigé sur tous les clustersCorrection à 17 h 53 UTC le 21/10 ; PHP 5.3 à 7.3 le 23/10
HostingerCertains sites affichent 8.5.11 au lieu de 8.5.12 : "This is expected"Repère conseillé : Build Date du 21/10 ou après
Kinsta"All sites are protected", déploiement sur toute la plateformeTerminé le 22/10 à 8 h 26 UTC
HetznerCorrectifs 5.6, 7.3, 7.4 et 8.0 à 8.5 sur les offres gérées (Webhosting, Managed)Clients des serveurs Cloud et dédiés prévenus à part, par e-mail
CloudLinuxPaquets alt-php corrigés "even though the PHP version number is lower"Dépôts stables complets le 22/10 à 0 h 07 UTC

Deux points de méthode sur ce tableau. D’abord, sur les serveurs Cloud et dédiés (Hetzner, les VPS en général), le correctif PHP est à votre charge, pas à celle de l’hébergeur : ne confondez pas "mon hébergeur a corrigé" et "mon offre gérée a été corrigée". Ensuite, méfiez-vous de ce que vous lisez ailleurs : j’ai croisé des pages affirmant que les branches 7.4 à 8.1 étaient "sans aucun correctif" (faux, des rétroportages existent), d’autres plaçant la publication à 14 h UTC alors que les deux avis GitHub sont horodatés à 13 h 34 UTC, et même une page qui inversait les mécanismes des deux CVE.

Faut-il quitter un hébergeur qui a tardé ?

Non, pas sur la seule impression d’avoir été tenu dans le flou. Jugez sur la preuve, pas sur le ressenti. Un hébergeur qui corrige dans la nuit mais communique le lendemain a fait l’essentiel : il a protégé votre site. Avant de claquer la porte, vérifiez le binaire avec la méthode ci-dessus, posez la question au support (journal du paquet, date de fabrication, confirmation que les processus ont redémarré). Ne partez que si la réponse ne vient pas, ou si elle est fuyante.

Ce que je regarde, moi, dans ces moments : la rapidité du geste technique, pas l’élégance du message. Un incident comme celui-là agit en révélateur : il montre quels hébergeurs tiennent leurs serveurs à jour sérieusement. C’est exactement ce que je creuse quand je fais un audit de sécurité WordPress en mission.

Que dire à ses clients, et quand le dire ?

Rien avant, un mot après. Pendant l’urgence, je corrige : envoyer un message alarmant à un client qui ne peut rien faire n’ajoute que de l’angoisse inutile. Une fois le correctif posé et vérifié, j’envoie un message court et factuel : c’est fait, voici la preuve. Le client n’a pas besoin de comprendre le détail du binaire, il a besoin de savoir que quelqu’un s’en est occupé et peut le démontrer.

Après le correctif, j’ai aussi fait une vérification d’intrusion, en lecture seule : comparaison des empreintes de fichiers avec la photo de référence du matin, recherche de motifs suspects dans le code, lecture des journaux d’accès autour de la fenêtre dangereuse. Aucun signe sur mon périmètre. Mais je connais la limite de l’exercice : une exploitation qui n’écrit rien sur le disque ne laisse que des traces dans les requêtes, et seulement si on les journalise. L’absence de signe n’est pas une preuve d’innocence, c’est une absence de signe.

Une faille critique ? Traitée dans le délai du contrat.

Découvrir la maintenance

Compiler PHP soi-même : à ne pas reproduire sans filet

J’ai compilé PHP depuis les sources cet après-midi-là pour deux raisons. Je savais exactement ce que je faisais, et j’avais posé un filet à chaque étape : instantané avant de toucher quoi que ce soit, binaire d’origine gardé pour un retour arrière en deux secondes, comparaison des modules chargés avant l’échange, contrôle des codes de réponse de chaque site après. Sans ce filet, je ne l’aurais pas fait.

Pour la plupart des sites, ce n’est ni nécessaire ni raisonnable. La bonne démarche : poser l’atténuation officielle le temps que ça dure (php.net prévient qu’aucune n’est complète), puis attendre le paquet de votre distribution ou de votre hébergeur, qui arrive en général dans la journée. L’avis SANS ISC le disait sans détour : "It will almost certainly be faster to wait for your distribution to release an update". Compiler soi-même un moteur critique dans l’urgence, sans environnement de test et sans plan de retour arrière, c’est le genre de geste qui règle une faille et en ouvre trois autres.

Un dernier point, apparu après coup. Le 23 octobre, l’équipe PHP a publié un avis complémentaire (CVE-2026-115560) : garder session.upload_progress.enabled=0 jusqu’à la prochaine version de maintenance, dans la configuration du serveur et non dans un .user.ini. J’ai donc maintenu ce réglage. Et je garde en tête que PHP 8.2 sort du support de sécurité le 31 décembre 2026 : les serveurs qui y restent devront migrer, ou ils seront la cible la plus facile du prochain PHP2Shell.

Questions fréquentes

Mon site affiche une version de PHP non corrigée, suis-je vulnérable ?

Pas forcément. Beaucoup d’hébergeurs et de distributions ont intégré le correctif sans changer le numéro de version (rétroportage). CloudLinux, O2switch, Ubuntu et AlmaLinux l’ont fait. Le numéro affiché ne tranche donc rien : cherchez la chaîne "Hard memory limit of" dans le binaire, ou demandez le journal du paquet à votre hébergeur.

Le réglage session.upload_progress.enabled=0 suffit-il ?

Non. Ce réglage ne couvre qu’une des deux failles, et seulement s’il est posé dans la configuration du serveur, pas dans un fichier .user.ini. L’avis officiel est explicite : "Do not rely on ini_set() or FPM .user.ini". C’est une atténuation temporaire. La mise à jour de PHP, suivie du redémarrage des processus, corrige les deux failles. Depuis le 23 octobre, php.net conseille en plus de garder session.upload_progress.enabled à 0 jusqu’à la prochaine version de maintenance, contre une troisième voie d’attaque jugée peu probable.

Comment vérifier sans accès en ligne de commande au serveur ?

Demandez à votre hébergeur le journal du paquet PHP (sur les systèmes RPM, rpm -q --changelog), qui indique en général si la correction des deux CVE y figure, numéro de version ou pas. Exception : les paquets PHP natifs 8.2 et 8.3 de CloudLinux, à juger sur leur numéro. À défaut, demandez-lui une confirmation écrite que le correctif est posé et que les processus PHP ont été redémarrés. La date de fabrication du binaire est un indice complémentaire, jamais une preuve à elle seule.

Et si je tourne encore en PHP 7.4, 8.0 ou 8.1 ?

Ces branches ne reçoivent plus de correctif du projet PHP. Des rétroportages de source minimaux existent pour 7.4, 8.0 et 8.1, mais c’est à votre distribution ou hébergeur de les intégrer, sans garantie, et ils n’ajoutent pas le marqueur dans le binaire (vérifié sur la branche 8.1). Sur ces versions, l’absence du marqueur ne permet pas de conclure : interrogez le fournisseur, et surtout, planifiez une migration vers une branche maintenue.

Sources

Pages lues et vérifiées entre le 20 et le 23 octobre 2026 ; citations anglaises laissées en version originale ; démonstration du marqueur menée le 23 octobre sur les binaires Windows officiels, sans exécution.

Mini-formation gratuite

Ces 7 templates, je les donne en formation payante. Ici, ils sont gratuits.

Sécurité, SEO, performance, contenu, maintenance - les outils que j'utilise en formation et en audit, avec les prompts IA pour aller 10x plus vite.

  • 01Workflow contenu anti-IA
  • 02Framework SEO Title/Meta/H1
  • 03Audit Express 30 points
  • 04Blindage sécurité 10 étapes
  • 05Performance web sans plugin
  • 06Calendrier maintenance IA
  • 07Plan d'action 90 jours

Double opt-in : confirme ton email, puis 1 email / 2 jours pendant 14 jours. WPFormation utilise les données saisies, via Brevo, pour votre inscription et les emails annoncés, avec votre consentement. Données jamais revendues. Désabonnement en 1 clic. Vos droits et la conservation de vos données

Fabrice Ducarme, formateur WordPress
Fabrice Ducarme

Référence francophone WordPress depuis 2012. Expert en IA (Claude, Gemini) et développement Headless (Next.js), je forme les professionnels à maîtriser l'écosystème web d'aujourd'hui et de demain.

Comment j'utilise l'IA pour écrire ces articles