Retour

php2shell : comment nous avons protégé plus de 6 millions de sites web


php2shell : comment nous avons protégé plus de 6 millions de sites web

PHP est le langage qui fait tourner une grande partie des sites web, dont l’ensemble des sites WordPress. Le 21 octobre, le projet PHP, qui développe ce langage, a publié les correctifs de deux failles critiques de PHP, surnommées « php2shell ». Elles portent les identifiants CVE-2026-109618 et CVE-2026-109619 (une CVE est la référence publique attribuée à chaque faille de sécurité connue).

Leur gravité est notée 9,2 sur 10 (score CVSS) : un attaquant peut faire exécuter ses propres commandes dans le contexte du site visé, sans le moindre identifiant. Pré-annoncées quelques jours plus tôt sans détail technique, ces failles ont vite attiré des scanners qui balaient le web à la recherche de serveurs vulnérables.

Notre pare-feu applicatif surveillait déjà ces attaques avant même la publication des correctifs. Ceux-ci ont été très rapidement déployés par nos soins sur l’ensemble de la plateforme, pour les quinze versions de PHP que nous proposons, y compris les huit qui n’ont reçu aucun correctif officiel.

Si votre site est hébergé sur nos offres d’hébergement web mutualisé, rassurez-vous : il est protégé, quelle que soit sa version de PHP. Vous n’avez rien à faire, le déploiement des correctifs est terminé sur toute la plateforme.

Ce billet s’adresse à nos clients et à toute personne curieuse de savoir comment une équipe d’exploitation absorbe une faille critique sur une flotte de 5 000 serveurs.

L’essentiel des faits

FaillesDeux failles du moteur PHP, surnommées « php2shell » : CVE-2026-109618 (un dépassement de mémoire mal géré) et CVE-2026-109619 (des données d'une requête qui restent lisibles par la suivante)
GravitéCritique (CVSS niveau 9,2 sur une échelle de 10) : un attaquant peut faire exécuter ses propres commandes dans le contexte du site visé, à distance et sans mot de passe
Versions corrigées par le projet PHPLes versions récentes : 8.2.35, 8.3.36, 8.4.27 et 8.5.12. Un correctif minimal existe pour 7.4, 8.0 et 8.1
Versions sans correctif officielPHP 5.3 à 7.3 : ces versions ne sont plus maintenues par le projet PHP, mais encore très répandues
Notre réponseDétection des attaques sur notre pare-feu applicatif dès la pré-annonce, mise à jour des versions récentes, correctif écrit par nos équipes pour PHP 5.3 à 7.3 (rétroportage), puis tests et double relecture avant déploiement
Ce que vous devez faireRien. Si votre site utilise encore PHP 5 ou 7, profitez-en pour passer à une version maintenue
À savoir si vous développezSi un script dépasse sa limite de mémoire (memory_limit), il s'arrête net : les fonctions de fin de script et les destructeurs ne s'exécutent plus (détails plus bas)

Ce qui s’est passé

Les deux failles naissent du même mécanisme : la façon dont PHP interrompt une requête qui dépasse sa limite mémoire.

PHP traite chaque requête HTTP dans un processus qui enchaîne les requêtes les unes après les autres. Quand un script dépasse sa limite mémoire, PHP saute brutalement à la fin de la requête, puis fait le ménage avant de passer à la suivante.

  • CVE-2026-109618 : si un script dépasse sa limite de mémoire pendant que PHP est encore en train de préparer la requête, PHP lance le ménage sur des données à moitié prêtes. Cela crée un état incohérent en mémoire. Un attaquant peut provoquer ce moment précis en envoyant un formulaire avec un fichier dont la taille est calculée pour ça.
  • CVE-2026-109619 : le ménage entre deux visites est incomplet. Des restes de la visite précédente peuvent être lus par la suivante. La porte d’entrée la plus simple est le suivi de progression des envois de fichiers (session.upload_progress) : cette fonction lit les données de session du visiteur avant même que le site ne démarre, c’est-à-dire au moment le plus fragile.

Combinés, ces deux défauts permettent dans certaines conditions d’exécuter du code arbitraire dans le contexte du site visé, sans aucun identifiant.

Pourquoi c’est un défi pour un hébergeur mutualisé

Un serveur dédié n’héberge généralement qu’un nombre très faible de sites : une faille y a donc un impact limité. Sur un hébergement mutualisé, au contraire, de nombreux sites sont regroupés sur un même serveur. Quand une version de PHP est touchée par une faille, c’est donc un grand nombre de sites qui sont concernés d’un coup. Et comme nos clients n’ont pas la main sur le moteur PHP, c’est à nous de corriger, vite et partout à la fois.

Notre plateforme compte environ 5 000 serveurs, en Europe et au Canada, sur lesquels sont hébergés plus de 6 millions de sites web. Nos clients choisissent librement leur version de PHP, de 5.3 à 8.5. Cette liberté permet de faire vivre des sites anciens, mais elle a un coût : plus de la moitié de ces versions ne reçoivent plus aucun correctif du projet PHP.

Le correctif officiel des versions maintenues compte près de 3 000 lignes et refond la gestion des dépassements mémoire au cœur du moteur. Il est impossible de l’appliquer tel quel à un PHP 5.6 ou 7.2. Pour 7.4, 8.0 et 8.1, le projet PHP a publié une mitigation minimale hors cycle. Pour les versions antérieures, rien n’existe : c’est à nous, OVHcloud, de le produire.

Notre réponse couche par couche

Nous avons empilé plusieurs couches de protection : la première arrête les attaques à l’entrée de la plateforme pendant que les suivantes corrigent PHP lui-même. Les spécialistes parlent de « défense en profondeur ». Voici nos cinq étapes, de la première alerte au déploiement sur tous les serveurs.

1. Détecter les tentatives d’attaque avant même l’application du correctif

Les versions corrigées officielles ne sont sorties que le 21 octobre à 16 h. D’ici là, il fallait protéger les sites autrement, et sans attendre.

Nos serveurs web sont précédés d’un pare-feu applicatif : un filtre que chaque visite traverse avant d’atteindre un site, et qui peut écarter les requêtes suspectes. Nous l’avons intégré nous-mêmes, à partir des outils libres OpenResty et NAXSI. Dès la pré-annonce du projet PHP, nous lui avons appris à reconnaître les traces caractéristiques de l’attaque, telles qu’un champ de formulaire précis (celui qui active le suivi de progression des envois de fichiers), certains user-agents (l’identifiant qu’envoie chaque navigateur ou robot) ou des contenus de requête typiques. Une seconde règle bloque les robots qui se sont mis à scanner le web à la recherche de sites vulnérables.

Cette règle a d’abord fonctionné en mode observation. Elle repérait les requêtes concernées sans les bloquer. Pourquoi cette prudence ? Ce même champ de formulaire est aussi utilisé en toute légitimité, par exemple par les sites qui affichent une barre de progression pendant l’envoi d’un fichier. Le bloquer d’emblée aurait pu casser ces sites. Observer d’abord nous a permis de mesurer combien de sites seraient touchés, tout en restant prêts à bloquer à tout moment.

2. Mettre à jour dès la sortie des correctifs officiels

Le 21 octobre à 16 h, le projet PHP a publié ses bulletins de sécurité et les versions corrigées officielles : 8.2.35, 8.3.36, 8.4.27 et 8.5.12. Pour PHP 8.2 à 8.5, toujours maintenues par le projet PHP, la situation est la plus simple. Le correctif officiel, qui refond en profondeur la gestion des dépassements mémoire, est inclus dans ces nouvelles versions. Nous les avons reprises telles quelles et compilées pour notre plateforme. Elles ont ensuite suivi les mêmes tests et le même déploiement progressif que les autres (étapes 4 et 5).

Pour 7.4, 8.0 et 8.1, qui ne reçoivent normalement plus de correctifs, le projet PHP a publié le même jour une mitigation minimale, hors de son calendrier habituel. Nous l’avons intégrée à nos paquets dans les heures suivantes.

3. Rétroporter nous-mêmes sur PHP 5.3 à 7.3

Pour PHP 5.3 à 7.3, en fin de vie, le projet PHP ne publie plus aucun correctif. Nous avons donc fait un rétroportage : adapter nous-mêmes à ces versions anciennes le correctif conçu pour les versions récentes. C’est la partie la plus délicate. Le moteur de PHP a beaucoup changé depuis ces versions, et le correctif officiel ne peut pas s’y appliquer tel quel. Nous en avons extrait ce qui pouvait s’adapter, en deux volets.

Le suivi de progression ne peut plus exécuter de code avant le démarrage du script. La mitigation officielle, celle publiée par le projet PHP, désactive purement et simplement cette fonctionnalité. Nous avons préféré la conserver, car des applications hébergées s’en servent, mais en la durcissant :

  • la session est décodée dans un mode où aucune classe n’est résolue, ni autoloader ni méthode magique ne s’exécute ;
  • les données sont réécrites à l’octet près ;
  • si le décodage échoue, la session est laissée intacte plutôt que détruite. C’est un écart volontaire par rapport au correctif officiel, pour ne jamais déconnecter un visiteur.

Un dépassement mémoire ne laisse plus le processus continuer avec un état corrompu. Le processus de travail se termine immédiatement et notre gestionnaire de processus en relance un neuf. Le message « Allowed memory size exhausted » reste visible dans vos journaux d’erreurs et sur la page en développement : beaucoup d’entre vous l’utilisent au quotidien, et la mitigation officielle l’aurait fait disparaître.

S’y ajoutent des durcissements plus discrets : limitation des en-têtes acceptés dans un corps multipart, respect strict de post_max_size pendant la lecture, remise à zéro systématique de l’état interne entre deux requêtes.

4. Vérifier à plusieurs et avec des tests

Un correctif de sécurité mal écrit peut casser des sites, voire ouvrir une nouvelle faille. Avant toute diffusion, chaque version a donc été compilée puis passée sur les batteries de tests automatiques du projet PHP, pour les parties concernées : les sessions, la sérialisation (la façon dont PHP enregistre des données pour les relire plus tard) et le cœur du moteur. Nous y avons ajouté des tests de non-régression écrits pour l’occasion : ils vérifient que ce qui fonctionnait avant le correctif fonctionne toujours après.

Les tests automatisés ne couvrent pas tout. Chaque rétroportage a donc fait l’objet d’une revue de code croisée. Ces relectures indépendantes ont mis au jour deux défauts qui avaient échappé aux suites de tests, corrigés avant diffusion :

  • certaines données complexes enregistrées dans la session d’un visiteur (un conteneur SPL, en termes techniques) pouvaient être réécrites de travers ;
  • dans un cas d’erreur particulier, la protection renforcée restait active pour toute la suite du script, alors qu’elle ne devait l’être que le temps de lire la session.

Enfin, nous avons comparé notre travail à celui des communautés Debian et Ubuntu, qui maintiennent elles aussi d’anciennes versions de PHP pour leurs utilisateurs. Elles ont fait des choix voisins des nôtres, ce qui conforte notre approche.

5. Déployer progressivement

Plutôt que de mettre à jour tous nos serveurs d’un coup, nous avançons par étapes. Les nouvelles versions de PHP, livrées sous forme de paquets (des fichiers d’installation prêts à l’emploi), sont d’abord installées sur nos clusters de préproduction, c’est-à-dire des groupes de serveurs qui servent à tester avant la mise en service réelle. Elles ne rejoignent la production qu’une fois validées.

Sur chaque serveur mis à jour, une vérification simple confirme deux choses : le correctif est bien présent dans le programme PHP installé, et PHP réagit comme prévu à un envoi de fichier et à un dépassement mémoire. Un problème éventuel est ainsi repéré avant de toucher l’ensemble des sites.

Si votre site est installé sur nos hébergements mutualisés, vous n’avez rien à mettre à jour ni à redémarrer : le déploiement automatique est désormais terminé sur toute la plateforme.

Ce que cela change pour vos sites

Pour la grande majorité des sites, rien de visible. Deux comportements changent toutefois, à connaître si vous développez sur PHP.

Sur un dépassement de memory_limit, le script s’arrête net. Le message d’erreur est inchangé, mais :

  • les fonctions enregistrées via register_shutdown_function ne sont plus exécutées ;
  • les destructeurs d’objets ne sont plus appelés ;
  • le contenu en tampon de sortie est perdu.

Si votre application s’appuie sur ces mécanismes pour journaliser une erreur ou nettoyer des ressources, c’est le moment de le vérifier. C’est le prix d’une protection complète sur ce chemin.

La barre de progression des envois continue de fonctionner. Dans les rares cas où une session ne peut pas être décodée, la progression n’est simplement pas enregistrée et la session du visiteur est conservée.

Si votre site tourne encore en PHP 5 ou 7, prenez ce billet comme un signal. Nous continuerons à protéger ces versions autant que possible. Mais une version maintenue reçoit ses correctifs en quelques heures, là où une version en fin de vie demande un travail d’orfèvre à chaque faille. Le changement de version se fait en quelques clics depuis votre espace client.

La chronologie

Quatre jours ont séparé la pré-annonce de paquets prêts pour quinze versions de PHP, dont huit sans aucun support officiel.

Mi-octobrePré-annonce par le projet PHP d'un correctif critique pour le 21 octobre, sans détail technique. Première signature de détection préparée.
21 octobre, matinSignature déployée en mode observation puis blocage sur tous les pare-feu applicatifs de la plateforme.
21 octobre, 16 hPublication des bulletins, des versions corrigées 8.2 à 8.5 et des mitigations 7.4, 8.0 et 8.1. Ces dernières sont intégrées à nos paquets le jour même.
21 octobre, soirRétroportage sur PHP 7.2 et revue indépendante, puis portages 5.6, 7.0, 7.1 et 7.3 en parallèle.
22 octobrePortages 5.3, 5.4 et 5.5. Ajout de l'arrêt du processus sur dépassement mémoire, de 5.3 à 7.3.
23 octobreRelecture d'équipe, publication des paquets pour les huit versions en fin de vie. Début et fin du déploiement progressif.

Partager sur :