Sources vérifiées au 22 octobre 2026. Audience : opérateurs d’applications PHP, intervenants en matière de sécurité et ingénieurs gérant des versions PHP personnalisées.

Cet article résume la cause, l’étendue de l’impact, le processus de réparation formel, les mesures d’atténuation temporaires et la mise en œuvre du correctif officiel de la vulnérabilité PHP2Shell. Le texte principal est cité à l’aide de chiffres tels que S1 ; tous les liens sources sont répertoriés en annexe à la fin du texte. Le fragment de configuration est un modèle de déploiement qui doit être ajusté en fonction de la version réelle, de la capacité de l’entreprise et de la relation d’héritage de configuration.

TL;DR : étapes de réparation et suggestions

  1. Mettez à niveau le runtime PHP : mettez à niveau la branche concernée vers au moins 8.2.35, 8.3.36, 8.4.27 ou 8.5.12. Pour les packages de distribution, utilisez la version complète du package dont le fournisseur confirme qu’elle corrige les deux CVE. S1S10
  2. Remplacez tous les anciens processus : redémarrez ou remplacez chaque PHP worker, service d’hébergement et conteneur après la mise à niveau, et confirmez que les anciennes instances se sont fermées.
  3. Vérifiez via le chemin de requête Web réel : vérifiez le Web SAPI, la version complète du package et l’instance en cours d’exécution. La vérification de php -v seule ne permet pas d’établir que le service en direct est corrigé.
  4. RExécutez des contrôles de régression commerciale et restaurez les budgets de ressources normaux : testez la connexion, la gestion des sessions, les téléchargements, les importations et la gestion des erreurs. Si la limite de mémoire PHP a été temporairement supprimée, restaurez un budget fini approprié après l’application du correctif.
  5. Si une mise à niveau immédiate est impossible : limitez le trafic non approuvé avant qu’il n’atteigne PHP. Évaluez la désactivation de la progression du téléchargement et des backtraces fatales PHP 8.5 comme décrit dans la section 5. Les atténuations de configuration et les règles WAF ont une couverture limitée et ne peuvent pas remplacer une mise à niveau. S1S2S3

1. Aperçu de la vulnérabilité et jugement des risques

PHP2Shell dans cet article fait référence à deux vulnérabilités de niveau Critical officiellement divulguées par PHP le 21 octobre 2026. Toutes deux sont liées à la gestion du cycle de vie de la mémoire et des requêtes du moteur PHP, posant le risque d’exécution de code à distance non authentifié. S1S2S3

ProjetCVE-2026-109618CVE-2026-109619
nom officielRCE via OOM corruptionRCE via stale global state
questions fondamentalesUne mémoire insuffisante provoque un saut anormal, laissant un état dont l’initialisation n’est pas encore terminée.L’état global restant dans le travailleur pointe vers la mémoire de requête libérée.
Heure d’occurrence typiqueLe processus d’initialisation, d’exécution ou de nettoyage de la requête en coursLa requête précédente quitte le statut et les requêtes suivantes le consomment à l’avance.
OOM est-il une condition nécessaire ?Appartient au principal mécanisme de déclenchement de la vulnérabilitéNon ; d’autres erreurs fatales et un nettoyage post-diagnostic peuvent également être impliqués
Direction de réparation fondamentaleGérer en toute sécurité les échecs d’allocation et les résiliations de demandesCorrection de la propriété de l’État, du calendrier de nettoyage et de l’initialisation précoce
Exigences d’éliminationdoit être réparédoit être réparé en même temps

Base : deux bulletins de sécurité officiels et soumissions de correctifs. S2S3S4

1.1 Comprendre les déploiements concernés

PHP considère officiellement tous les déploiements PHP traitant les demandes Web à risque, notamment PHP-FPM, Apache mod_php, php-cgi, FrankenPHP et LiteSpeed. L’attaque mod_php démontrée peut se produire avant l’exécution du code de l’application, de sorte que les contrôles de connexion, le middleware du framework et la validation du téléchargement de l’application ne peuvent pas couvrir ce chemin. S1

Il faut faire la distinction entre « le déploiement doit être corrigé » et « une certaine chaîne d’attaque a été pleinement prouvée ». Annonce de CVE-2026-109618 : FPM quittera le processus enfant après l’échec du démarrage de la requête, bloquant le chemin de nettoyage correspondant de mod_php après l’échec du démarrage ; cependant, le chemin OOM après un démarrage réussi est toujours menacé. L’annonce indique également que l’exploit complet FPM pour ce CVE n’a pas encore été démontré. Cette restriction ne peut pas être utilisée pour déduire que FPM est sûr, en particulier CVE-2026-109619 ne peut être ignoré. S2S3

Les limites d’autorisation immédiates pour une exploitation réussie dépendent de l’identité du processus hébergeant PHP et des ressources auxquelles il a accès. Généralement, une attention particulière doit être portée au code du site Web, au répertoire de téléchargement, aux informations d’identification de la base de données, aux jetons de service et aux capacités d’accès au réseau interne ; « exécution de code à distance » ne signifie pas obtenir naturellement les autorisations root. Le jugement des conséquences est ici basé sur le modèle d’autorisation de processus, et l’impact réel doit être évalué en conjonction avec les autorisations de déploiement.

Les scripts CLI ordinaires à usage unique n’ont pas la même entrée HTTP ; mais les processus qui gèrent des tâches externes pendant une longue période en CLI ou en mode intégré doivent toujours être inclus dans l’inventaire d’exécution et de cycle de vie. Seules les dépendances CMS, framework ou Composer sont mises à jour et le moteur PHP sous-jacent n’est pas automatiquement remplacé.

2. Analyse des causes

2.1 Comprendre d’abord les deux cycles de vie

PHP worker traite souvent plusieurs demandes successivement. La mémoire allouée lors de la requête peut être libérée uniformément à la fin de la requête, tandis que le travailleur lui-même et certains de ses champs globaux continuent d’exister.

Le moteur doit donc respecter deux contraintes :

  • Contrainte d’initialisation : les données visibles par d’autres codes doivent être dans un état qui peut être lu, parcouru et détruit en toute sécurité.
  • Contrainte de cycle de vie : une fois la mémoire de requête libérée, les champs à durée de vie plus longue ne doivent plus continuer à traiter les adresses de cette mémoire comme un état valide.

Ces deux contraintes correspondent aux principaux modes de défaillance des deux groupes de vulnérabilités. Le processus suivant est une description du mécanisme qui combine les annonces et la compilation des correctifs. Cela ne signifie pas que chaque déploiement a exactement le même chemin accessible. S2S3S5

2.2 CVE-2026-109618 : OOM a interrompu une mise à jour de statut inachevée

L’ancienne implémentation utilise un saut non local de type longjmp() pour gérer OOM, et le chemin associé quitte le contexte d’exécution actuel via zend_bailout(). Le danger est qu’un morceau de code C peut avoir publié un nouvel objet, un tableau ou un nouvel état de demande dans un autre code, mais n’a pas encore terminé l’initialisation de tous les champs ; à ce moment-là, tout échec d’allocation au moment concerné peut entraîner le saut des étapes normales de clôture. S2

Le processus d’échec peut être décomposé en quatre étapes :

  1. Créez ou mettez à jour la structure interne de la demande et rendez-la accessible.
  2. L’allocation de mémoire ultérieure échoue et OOM est déclenchée.
  3. Le flux d’exécution s’éloigne de la fonction actuelle et le code initialement utilisé pour terminer l’initialisation ou la restauration de l’état n’est pas exécuté.
  4. Le nettoyage des demandes continue de traiter ces structures et traite les contenus non valides comme des champs ou des adresses valides.

Le problème n’est pas que le manque de mémoire provoque toujours RCE. Au lieu de cela, l’épuisement de la mémoire modifie le flux de contrôle et viole les hypothèses du moteur concernant les structures valides. L’échec de l’allocation n’implique pas nécessairement directement la structure qui est finalement mal lue. S2

Pourquoi les requêtes plus petites peuvent également manquer de mémoire

Le nombre d’octets dans le corps de la requête et l’utilisation du tas après l’analyse ne sont pas la même chose. Le champ A peut correspondre à plusieurs chaînes, éléments de tableau et objets de métadonnées à l’intérieur de PHP ; la complexité structurelle d’entrée affectera le degré d’amplification de la mémoire.

Les problèmes liés au multipart répertoriés dans l’annonce officielle incluent : un écart de vérification de la taille initiale lorsque la longueur de déclaration disponible est manquante, le nombre d’en-têtes pour une seule partie n’est pas suffisamment limité et les contrôles de fichiers vides produisent toujours des métadonnées, avec des noms imbriqués augmentant encore la charge de travail du tableau. Le déroulement, le décodage ou la réaffectation des entrées par l’application peuvent également être une source de OOM. S2

Deux conclusions protectrices peuvent en être tirées :

  • Les restrictions du corps de la demande doivent être mises en œuvre autant que possible avant de saisir PHP, et la longueur de lecture réelle et la complexité structurelle doivent être prises en compte.
  • Limiter individuellement la taille et le nombre de fichiers ou fermer un seul portail de téléchargement ne peut pas couvrir toutes les sources OOM.

Pourquoi l’authentification des applications peut être trop tardive

Dans mod_php, le corps de la demande peut être automatiquement analysé pendant la phase d’initialisation de la demande ; même si le démarrage échoue, le nettoyage des requêtes associées sera toujours effectué. Des chemins d’attaque confirmés peuvent donc survenir avant le code de l’application. Pour réduire l’exposition à ce stade, des restrictions doivent être placées au niveau du proxy inverse, du serveur Web ou de toute autre limite précédant le traitement des requêtes PHP. S1S2

2.3 CVE-2026-109619 : La mémoire de requête a été libérée, la référence globale est toujours active

Ce problème concerne le statut d’erreur, de session, d’objet ou d’extension : le champ est stocké dans un emplacement d’accès à long terme de travailleur, mais les données référencées par le champ appartiennent à une seule requête. Tant que la référence n’est pas correctement nettoyée avant la libération du tas de requêtes, les requêtes ultérieures peuvent rencontrer un état en suspens, formant une utilisation après libération. S3

L’analyse officielle divise les conditions d’exploitation en « producteurs » et « consommateurs » :

rôle ou conditionsensImplications pour la protection
producteur d’étatPlacez l’État appartenant à cette requête dans un emplacement toujours accessible ultérieurement.Pour vérifier si le nettoyage correspondant est terminé après une sortie anormale
Le statut resteIl n’a pas été vidé, ou bien il a été vidé puis rempli à nouveau par une opération tardive.Un simple nettoyage une fois lors de la phase d’arrêt antérieure peut ne pas suffire
réutilisation des travailleursLe même travailleur continue de traiter les demandes ultérieuresPlusieurs travailleurs ne sont qu’une différence de planification, pas une garantie de sécurité de la mémoire
consommateur avancéLire, libérer ou déterminer la valeur résiduelle avant que l’état correspondant ne soit initialisé normalement.Doit vérifier INI, la session et les autres chemins avant l’initialisation

Ces conditions doivent être remplies ensemble ; tout journal d’erreurs ne prouve pas en soi que la vulnérabilité a été exploitée avec succès. S3

Il ne nécessite pas OOM comme condition préalable nécessaire

Des erreurs fatales peuvent interrompre la publication et la restauration de l’état apparié. Les échecs de compilation ou d’analyse, les erreurs non détectées, les échecs require et les délais d’attente d’exécution peuvent laisser des états particuliers derrière eux. Les diagnostics non fatals effectués tard dans le nettoyage peuvent également remplir à nouveau les informations d’erreur déjà effacées. S3

Par conséquent, la modification de memory_limit en illimité ne couvre pas cet ensemble de vulnérabilités.

”Avant l’initialisation” doit être traité séparément

Le timing des deux types de consommateurs confirmés est différent :

  • Diagnostic INI précoce : certaines configurations appliquées sur demande émettent un avertissement, un avis ou une dépréciation avant l’initialisation normale de l’exécuteur, et le traitement du diagnostic peut accéder à l’ancien état d’erreur.
  • progression du téléchargement de session : la session peut être traitée à l’avance pendant le processus d’analyse du corps de la demande, mais le module régulier RINIT n’est pas encore terminé ; on ne peut pas en déduire que le chemin n’existe pas car l’application n’appelle pas explicitement session_start(). S3

Toutes les configurations INI ne présentent pas le même timing de risque. La configuration au niveau du répertoire de mod_php et de PHP_VALUE / PHP_ADMIN_VALUE transmise par le frontal FPM doit être distinguée de la configuration de démarrage ordinaire php.ini, FPM pool et FPM .user.ini. Ces derniers ont des timings de configuration différents et ne peuvent pas être collectivement appelés les mêmes premiers consommateurs. S3

La désactivation de display_errors, log_errors, la réduction de error_reporting ou l’utilisation de @ n’affectent que la visibilité du diagnostic ; l’état interne concerné peut avoir été consulté avant de décider s’il faut sortir ou non le journal. S3

3. Version de réparation et sélection de correctifs

3.1 Référence de correction officielle en amont

Branche actuelle PHPLa première version à inclure ce correctif officielsuggestion
8.28.2.35Mise à niveau vers cette version ou une version ultérieure contenant les mêmes correctifs
8.38.3.36Idem que ci-dessus
8.48.4.27Idem que ci-dessus
8.58.5.12Idem que ci-dessus
8.1 et versions antérieuresLe support général en amont a pris finPrioriser la migration vers les branches prises en charge ; version de contrôle à court terme ou rétroportage du fabricant LTS

La version et l’état du support sont basés sur l’annonce officielle de PHP et la date de référence est le 22 octobre 2026. S1

Il s’agit de seuils de correctifs spécifiques à la branche. Ils ne peuvent pas être remplacés par une déclaration indiquant que chaque version inférieure à 8.5.12 est vulnérable : les versions telles que 8.2.35 et 8.4.27 dans d’autres branches contiennent déjà les correctifs.

3.2 Vérifiez la version complète du package de distribution

Les distributions ajoutent souvent des correctifs de sécurité basés sur les anciennes versions en amont. L’acceptation doit également vérifier la version finale, la source du référentiel, la version complète du package et le bulletin de sécurité.

Par exemple, la version du package de correctifs Ubuntu 24.04 LTS répertoriée pour Ubuntu USN-8948-1 est :

8.3.6-0ubuntu0.24.04.13

Sa partie amont est toujours 8.3.6, mais la version complète du package de cette distribution est incluse dans cette annonce de correctif. Cette conclusion s’applique uniquement à la distribution et à la source du package correspondants et ne peut être généralisée à aucune version affichant également 8.3.6. S10

3.3 Choisir le bon patch

scènePlan prioritairePoints clés pour l’acceptation
Utilisation du package de distribution PHPInstaller les mises à jour de sécurité publiées par le fabricantL’annonce couvre à la fois CVE ; la version complète du package est correcte
Utilisez le conteneur officiel PHP ou l’image auto-construiteMettre à jour le runtime de base, reconstruire et déployerL’instance en cours d’exécution utilise la nouvelle image ; toutes les anciennes copies sont sorties
Branches prises en charge auto-compiléesUtilisez la version de sécurité officielle de cette branche ou l’ensemble complet de correctifs officielsCorrespondance de branches, complétion des dépendances, compatibilité des extensions et transmission de régression
Soumis à 7.4, 8.0, 8.1Donner la priorité au rétroportage des fournisseurs ; évaluer la branche officielle du code source d’urgence si nécessaireIdentifier les changements de comportement et planifier la migration vers les versions prises en charge

Des correctifs officiels ont été publiés et les correctifs réels devraient commencer à partir de ces correctifs. Les extraits de code de la section 6 sont destinés à illustrer les points forts de la conception et de la révision et ne constituent pas un correctif complet pouvant être appliqué indépendamment. S1S4S6

4. Processus de réparation formel

4.1 Inventaire du runtime qui gère réellement les requêtes

Il est recommandé de constituer un bref registre pour enregistrer au moins :

  • Nom de domaine ou service d’entrée, backend de proxy inverse, PHP SAPI.
  • Branche PHP, version complète du package ou résumé d’image, source de build.
  • FPM pool, unité de service réelle, conteneur ou Pod, nombre de répliques.
  • Les extensions, la configuration principale et les fichiers de configuration supplémentaires ont été chargés.
  • Existe-t-il d’autres versions de PHP, d’anciennes copies de déploiement ou des portails d’origine accessibles directement ?

Ce sont des suggestions de mise en œuvre afin que « mise à niveau » puisse correspondre à chaque entrée de trafic réelle. Vérifiez notamment si les lignes de commande PHP et Web PHP utilisent des versions différentes, l’image est construite mais l’ancien conteneur est toujours en cours d’exécution, une partie du pool ou la copie n’est pas remplacée, etc.

4.2 Sélectionnez et déployez la bonne mise à jour

Confirmez la version du correctif conformément à la section 3, de préférence en utilisant une source de package fiable existante ou une chaîne de construction contrôlée. La portée de la mise à jour doit inclure le composant qui héberge réellement la demande, tel que le package FPM, le module Apache PHP, le binaire CGI ou la version de service dans laquelle PHP est intégré.

Avant la mise à niveau, conservez la configuration et la liste des packages, et vérifiez le démarrage et les services clés dans un environnement similaire à la production. Pour les extensions auto-entretenues, vérifiez la compatibilité de build et d’exécution correspondant à la version PHP. Le simple fait de choisir un commit apparemment pertinent dans une autre branche ne garantit pas que l’ensemble des correctifs a été implémenté.

4.3 Redémarrer ou restaurer les instances en cours d’exécution

Installer un fichier et charger un nouveau code dans un processus sont deux choses différentes. Le service correspondant doit être redémarré, ou le remplacement progressif doit être terminé, et l’ancien travailleur et l’ancien conteneur doivent être confirmés comme étant sortis.

Pour mod_php, redémarrez le processus Apache hébergeant le module. Les services qui intègrent PHP doivent remplacer leur processus d’hébergement. Pour FPM, la suppression de OPcache ne remplace pas la mise à jour du runtime et le retrait des anciens travailleurs.

Lorsque vous utilisez la commutation gracieuse, vous devez vérifier si le processus de l’ancienne génération gère toujours des connexions longues ou des demandes en attente. L’enregistrement d’acceptation doit inclure le service réel, la version de déploiement, l’heure d’achèvement de la modification et les résultats de sortie de l’ancienne instance.

4.4 Vérifier via de vraies demandes Web

Il est recommandé de combiner les éléments de preuve suivants plutôt que de s’appuyer uniquement sur une seule commande de version :

preuveQue peut-on prouverJe ne peux rien prouver seul
Gestionnaire de packages ou métadonnées d’imageSources d’installation et versions complètesLe trafic a été basculé vers cette instance
Statut du processus et du déploiementle travailleur ou le conteneur termine le remplacementL’entrée extérieure doit y être acheminée
Résultats de diagnostic restreints accessibles via un portail réelWeb SAPI réel et configuration en cours d’exécutionSi le backport de version couvre deux CVE
Annonce du fournisseur ou enregistrement complet des correctifsCe correctif de bug est inclus dans cette versionToutes les répliques sont déployées

Les PHP_VERSION, PHP_SAPI, les fichiers de configuration chargés et les configurations d’urgence peuvent être vérifiés via les capacités de diagnostic internes existantes ou via des portails de diagnostic temporaires et à accès contrôlé. Assurez-vous que la requête n’est pas renvoyée directement par CDN ou par le cache de pages ; supprimez l’entrée de diagnostic temporaire une fois terminé.

php -v indique généralement uniquement le binaire CLI actuellement sélectionné par le shell ; les commandes telles que php-fpm -i ne sont pas équivalentes à la vérification du travailleur existant qui reçoit du trafic. N’exposez pas la page phpinfo() complète au réseau public pendant une longue période.

4.5 Vérifications de régression commerciale et suppression des paramètres d’urgence

Vérifiez la connexion normale, la lecture et l’écriture de session, le formulaire et le téléchargement, l’importation, la gestion des erreurs et la stabilité des travailleurs autour des fonctions affectées par ce changement. Vérifiez si le taux d’erreur, le délai de réponse, le pic de mémoire, la sortie du processus et la fréquence de reconstruction sont anormaux.

Si memory_limit=-1 est temporairement défini, le budget limité correspondant à la capacité commerciale sera restauré après l’entrée en vigueur du correctif officiel ; si pm.max_requests=1 est défini, la configuration du cycle de vie évaluée en capacité sera restaurée une fois la réparation confirmée. Les limites de taille d’entrée et les contrôles d’accès aux sources peuvent être conservés selon les besoins de l’entreprise.

Si des problèmes de compatibilité surviennent lors de la mise à niveau, la priorité doit être donnée à la suspension du portail concerné, à la restriction de son accès externe ou à l’ajustement de l’application avant de revenir en arrière. Permettre directement au runtime non réparé de servir à nouveau le réseau public réouvrira le risque initial.

5. Mesures d’atténuation lorsqu’une mise à niveau immédiate n’est pas possible

Cette section est destinée à la réduction à court terme de l’exposition ou à l’amélioration de la disponibilité. Chaque mesure ne couvre qu’un chemin spécifique, et une combinaison de plusieurs mesures n’équivaut pas à une réparation complète. S1S2S3

5.1 Prioriser les contrôles de circulation avant PHP

Si le service le permet, limitez temporairement les points de terminaison sensibles aux sources fiables ou appliquez le contrôle d’accès avant PHP. Pour les charges de travail de téléchargement, limitez la taille du corps de la requête, le nombre de champs, le nombre de pièces, les en-têtes par pièce et la profondeur d’imbrication. Les services qui n’ont pas besoin de multipart peuvent le rejeter au niveau du frontend. S2

Ces restrictions doivent couvrir toutes les entrées du PHP. Seule l’interception du URL nommé « télécharger » manquera les autres entrées qui sont toujours automatiquement analysées par PHP dans le corps de la requête. Pour des cas tels que des transferts fragmentés, un manque de longueur déclarée disponible, etc., la limite doit être basée sur la taille de lecture réelle ; l’application doit également disposer de son propre budget de taille de sortie lors de la décompression ou de l’extension du contenu.

Modèle de configuration 5.2 FPM pool

Placez les paramètres suivants dans la section de configuration FPM pool qui sert réellement les requêtes, et non textuellement dans php.ini. Les valeurs 8M et 4M sont des exemples à ajuster en fonction de la charge de travail. Laissez de la place aux champs de formulaire et aux limites en plusieurs parties lorsque vous limitez l’intégralité de la requête POST. S11S12

; Temporary mitigation: evaluate capacity before applying.
php_admin_value[memory_limit] = -1
php_admin_value[post_max_size] = 8M
php_admin_value[upload_max_filesize] = 4M
php_admin_flag[session.upload_progress.enabled] = off

PHP 8.5 uniquement, plus :

php_admin_flag[fatal_error_backtraces] = off

Les fonctions et limites de chacun sont les suivantes :

Configurationeffet attenduDescription des restrictions qui doivent être retenues
memory_limit=-1Supprimer la condition de déclenchement de limite supérieure de mémoire de requête prévisible PHPCela n’empêche pas l’échec d’allocation sous-jacent ; l’annulation du budget initial peut augmenter le risque d’épuisement de la mémoire et d’interruption du service.
Plus petit post_max_sizeRéduisez la taille des données entrant dans le processus d’analyseL’analyseur non corrigé présente un écart connu ; l’amplification de la mémoire ne peut pas être évitée indépendamment
upload_max_filesize < post_max_sizeLimiter la taille d’un fichier unique et réserver de l’espace supplémentaire pour les demandesNe limite pas tous les champs, métadonnées ou allocations dans l’application
Fermer la progression du téléchargementBloquer le chemin lié à la session confirméeNe couvre pas les autres variantes d’état global
PHP 8.5 fermer la trace fataleBloquer les producteurs au statut apparenté confirméNe couvre pas d’autres chemins tels que la session

Les limites des mesures proviennent de l’annonce officielle ; pour la syntaxe du pool et la sémantique de configuration au niveau de la gestion, consultez le manuel PHP. S1S2S3S11

Les paramètres php_admin_* au niveau de la gestion ne peuvent pas être remplacés par les applications via ini_set(). Toutes les configurations entrantes du pool, au niveau du répertoire et du front-end doivent toujours être examinées pour confirmer que les valeurs des demandes réelles sont conformes aux attentes. Après modification, reconstruisez tous les travailleurs pour empêcher les processus existants de continuer à conserver l’ancien état.

Si vous choisissez de modifier directement php.ini, la syntaxe doit être modifiée comme suit :

memory_limit = -1
post_max_size = 8M
upload_max_filesize = 4M
session.upload_progress.enabled = Off

Contrairement à php_admin_value dans le pool, le simple réglage de memory_limit=-1 dans php.ini n’empêche pas l’application de le modifier à nouveau. Le framework, le code de l’application et les autres configurations doivent être vérifiés pour voir s’ils ont réinitialisé la valeur limitée ; lorsque l’application est requise, utilisez les paramètres de niveau de gestion appropriés pour le SAPI actuel et vérifiez la valeur effective réelle. S11S12

Ajoutez fatal_error_backtraces = Off uniquement pour PHP 8.5. N’utilisez pas ini_set() au niveau de l’application comme solution de contournement pour désactiver la progression du téléchargement, et ne comptez pas sur FPM .user.ini pour le rendre efficace avant l’analyse de la demande. S1S3

5.3 Gérer le coût de suppression des limites de mémoire PHP

memory_limit=-1 est une atténuation de chemin temporaire pour les environnements non corrigés et ne doit pas être copiée en tant que configuration par défaut à long terme. Lorsqu’une application ou une requête devient incontrôlable, elle peut utiliser davantage de mémoire de l’hôte. Par conséquent, avant utilisation, vous devez évaluer le nombre de simultanéités, le pic de nœud de calcul unique et la capacité totale du service, et déployer des limites d’entrée frontales. S2

Les limites de mémoire des conteneurs ou des groupes de contrôle peuvent fournir des limites de disponibilité mais ne garantissent pas que les allocations n’échoueront jamais ; l’ensemble du conteneur, du maître et de tous les travailleurs peuvent également être résiliés lorsque la limite est déclenchée. La granularité de l’isolement et les stratégies de terminaison doivent être évaluées en conjonction avec le déploiement et ne peuvent pas être qualifiées de protection complète pour ces deux CVE. S2

Ne remplacez pas les stratégies ci-dessus par RLIMIT_AS, RLIMIT_DATA ou des restrictions d’espace d’adressage de processus correspondantes ; ils peuvent directement provoquer l’échec de l’allocation sous-jacente dans le chemin OOM, toujours problématique. S2

Exemple de configuration 5.4 Nginx

Applicable au déploiement dans lequel Nginx transmet les demandes à PHP-FPM. Il peut être défini au niveau de la configuration du service d’hébergement lui-même :

client_max_body_size 8m;
fastcgi_request_buffering on;

client_max_body_size limite la taille du corps de la demande ; fastcgi_request_buffering on permet à Nginx de lire d’abord le corps complet de la requête, puis de l’envoyer au backend FastCGI. Que cela prenne effet dans un certain server ou location doit être vérifié en conjonction avec les relations d’héritage et de couverture existantes. S13S14

Uniquement lorsque l’entreprise n’a pas besoin de multipart, vous pouvez ajouter une règle de rejet à l’entrée de service correspondante :

if ($http_content_type ~* "multipart/form-data") {
    return 403;
}

Il s’agit d’un simple modèle de restriction d’entrée utilisant if et return, et non d’une règle de filtrage générale pour les vulnérabilités de l’analyseur. Vérifiez la syntaxe de configuration et les requêtes normales avant le déploiement, et vérifiez si le error_page personnalisé redirige les requêtes 403 vers PHP. La correspondance de chaînes ne fournit pas de garanties complètes sur toutes les différences d’analyse. S15

De plus, ces configurations ne limitent pas automatiquement la quantité de données, le nombre de champs ou le nombre d’objets PHP pouvant être décompressés par l’application ; les entreprises qui ont besoin de télécharger doivent utiliser des restrictions supplémentaires qui comprennent la structure de leurs demandes.

5.5 Atténuation facultative : une demande par travailleur FPM

Pour les déploiements FPM qui peuvent supporter les frais généraux, les configurations à court terme peuvent être évaluées :

pm.max_requests = 1

Et reconstruisez le travailleur existant. Cela bloque la chaîne de requêtes croisées décrite au niveau de la réutilisation des travailleurs, mais augmentera la surcharge de création et d’initialisation des processus ; en même temps, il ne peut pas réparer la même demande OOM et les problèmes de nettoyage de CVE-2026-109618. Lorsque la valeur est inférieure mais supérieure à 1, il existe toujours une fenêtre de demande de réutilisation. S3S11

Limites de couverture 5.6 WAF et Cloudflare

Cloudflare a annoncé des modalités de déploiement pour la protection contre PHP2Shell, y compris le plan Free. Lorsque vous utilisez ses services, vous devez vérifier si le trafic réel passe par le proxy, si les règles de protection sont en vigueur et si le site d’origine peut être directement contourné ; pour les forfaits payants, vous devez également vérifier la configuration et les exceptions des règles gérées correspondantes. S16

Certaines des détections décrites par le fournisseur utilisent des signaux de réponse, de sorte que toutes les protections ne peuvent pas être interprétées comme « chaque attaque est bloquée avant d’atteindre PHP ». WAF peut aider à réduire l’exposition et fournir des informations d’observation, mais des mises à niveau continues vers PHP sont toujours nécessaires. S16

5.7 Pourquoi les mesures communes sont insuffisantes

mesures ou jugementslacunes
Fermer uniquement file_uploadsImpossible de couvrir tout le traitement en plusieurs parties et d’appliquer son propre chemin OOM
Paramètre enable_post_data_reading=OffModifier le comportement du remplissage automatique de POST/FILES ; le corps de la requête peut toujours être lu par l’application et peut perturber les activités normales
Désactivez l’affichage des erreurs, enregistrez ou utilisez @Le traitement de diagnostic interne peut toujours accéder à l’état en suspens
Augmenter la quantité de travailleurN’établissez pas de mécanisme de nettoyage d’état sûr, ni n’éliminez la réutilisation d’un seul travailleur
Configurez uniquement disable_functions ou open_basedirCes limitations ne corrigent pas la corruption de la mémoire de la couche moteur C.
Vérifiez une version ou une seule copie une seule foisIl ne peut pas être prouvé que toutes les entrées et instances en cours d’exécution ont été remplacées.
Aucun journal d’exception n’est visibleIl ne peut pas prouver que la vulnérabilité n’existe pas ou qu’elle n’a pas été exploitée auparavant.

Parmi eux, la base du mécanisme de configuration et de vulnérabilité de PHP se trouve dans S2S3S12 ; les jugements sur les limites de couverture, d’acceptation et d’autorisation sont basés sur les suggestions de mise en œuvre avancées par ces mécanismes.

6. Idées d’implémentation et points de révision du patch officiel

6.1 Utiliser les correctifs complets pour la branche appropriée

La soumission officielle représentative pour PHP 8.5 est :

31c0ea7d7ff1d1fccb6492e52dab544011628065
Avoid state corruption via bailout

Le commit associe explicitement deux CVE, à la fois pour ajuster le mécanisme de sortie de OOM et pour corriger l’état global accessible pendant la phase d’initialisation. Soumettre la page avec la différence complète, voir S4S5. Les autres branches doivent utiliser leurs propres versions de sécurité officielles ou correctifs correspondants, et on ne peut pas supposer que les modifications apportées à 8.5 peuvent être directement appliquées à une version antérieure.

6.2 OOM Réparation : restaurez d’abord l’état traitable, puis terminez la demande

L’implémentation formelle introduit deux niveaux de traitement OOM soft et hard : lorsque la limite soft est atteinte, l’état en attente est enregistré et une sortie contrôlée est effectuée dans un emplacement sûr tel que VM ; l’interface d’allocation défaillante permet à l’appelant de gérer explicitement l’échec. Pour les allocations qui ne peuvent pas renvoyer directement un échec, si un seuil strict plus élevé est susceptible d’être dépassé, le processus sera terminé directement pour éviter de continuer à traiter les demandes dans un état intermédiaire dangereux. S2S5

Ce qui suit est un extrait du code clé dans le diff 8.5 utilisé pour marquer le OOM en attente :

EG(delayed_oom).state = ZEND_OOM_STATE_PENDING;
zend_atomic_bool_store_ex(&EG(vm_interrupt), true);

La gestion des interruptions VM et d’autres emplacements sûrs appellent ensuite zend_handle_delayed_oom(). Son contexte d’exécution de code utilisateur utilise un chemin de déroulement contrôlé ; le chemin dur OOM appelle _exit(137). S5

Du point de vue de la conception, les changements importants sont les suivants : évite de traverser arbitrairement la pile d’appels C lorsque la structure est dans un état intermédiaire et place la sortie à un emplacement qui peut maintenir les contraintes d’état. Une fois la limite logicielle déclenchée, de la mémoire supplémentaire peut être nécessaire pour terminer le processus, de sorte que le nouveau seuil logiciel ne peut pas être compris comme une limite supérieure absolue pour la mémoire totale du processus.

Cela ne peut pas non plus être résumé par « PHP a supprimé tous les zend_bailout() ». Le correctif utilise toujours des mécanismes pertinents dans des contextes spécifiques ; ce qui est corrigé, c’est le moment dangereux de la sortie et la gestion de l’État qui l’accompagne. S5

6.3 Mettre à jour les appelants d’allocation et l’analyse en plusieurs parties ensemble

Si vous modifiez uniquement une fonction d’allocation en “retourner NULL en cas d’échec” et que l’appelant d’origine suppose toujours qu’un pointeur valide est toujours renvoyé, vous introduirez de nouveaux accès au pointeur nul ou un nettoyage incomplet. L’interface d’allocation défaillante dans le correctif doit être revue ainsi que la vérification des appelants et la propagation des exceptions. S5

Les correctifs liés à plusieurs parties incluent également l’exécution de vérifications cumulatives basées sur le volume de lecture réel, la réduction du traitement des en-têtes inutiles ou en double et l’adoption d’une logique de sortie et de nettoyage cohérente lorsque OOM est en attente. Ces modifications réduisent à la fois l’amplification des ressources et rendent l’analyseur conforme au nouveau protocole OOM. S5

Pour les équipes qui gèrent leurs propres branches, il est recommandé que les problèmes suivants soient au centre de la révision du code :

  • L’état est-il visible du monde extérieur avant d’être complètement initialisé ?
  • Après un échec d’allocation ou une exception de rappel, la propriété est-elle toujours unique et sans ambiguïté ?
  • Pouvez-vous atteindre la sortie du nettoyage unifié si vous échouez à mi-chemin ?
  • La fonction de nettoyage peut-elle reconnaître les champs non initialisés ou libérés ?
  • Le budget d’analyse est-il basé sur le volume de traitement réel, et pas seulement sur les demandes de confiance ?
  • La nouvelle valeur de retour d’échec a-t-elle été gérée par tous les appelants ?

Il s’agit de questions d’examen résumées sur la base du mécanisme de correction et ne constituent pas la conclusion d’un audit effectué pour une base de code non fournie.

Correction de demandes croisées 6.4 : initialisation plus tôt, nettoyage final plus tard

Correspondant à CVE-2026-109619, le correctif ajuste simultanément plusieurs limites du cycle de vie. Les fichiers et opérations répertoriés ci-dessous prennent comme exemple le diff officiel PHP 8.5. S5

emplacementchanger de directionProblème résolu
Zend/zend_execute_API.c etc.Réinitialiser l’état de l’exécuteur tel que les erreurs, les exceptions, les gestionnaires, les objets, etc.Une fois la requête terminée, il reste d’anciennes références accessibles par la requête suivante.
Chemin de démarrage de main/main.cAppelez php_basic_early_rinit() avant que SAPI ne soit activéLorsqu’un consommateur précoce se produit, l’état sous-jacent concerné n’a pas encore été initialisé.
Fermer le chemin de main/main.cDétruisez HTTP globals et marquez-le comme indéfiniLa valeur validée est toujours considérée comme un objet valide
avant que le tas de requêtes ne soit finalement libéréNettoyez à nouveau le dernier message d’erreurLes diagnostics de nettoyage tardif repeuplent l’état d’erreur
ext/session/session.cprogression du téléchargement Le premier chemin est initialisé dans les globaux de la première sessionModule régulier RINIT précédemment accédé à l’ancien état
Code lié à la sérialisationLimiter l’analyse des classes et les rappels des utilisateurs au début du traitementExécuter du code utilisateur supplémentaire lorsque l’initialisation n’est pas terminée

Par exemple, la séquence de démarrage comprend :

zend_activate();
php_basic_early_rinit();
sapi_activate();

Une fois HTTP globals détruit, ajoutez la marque d’échec d’état :

zval_ptr_dtor(&PG(http_globals)[i]);
ZVAL_UNDEF(&PG(http_globals)[i]);

Ces extraits illustrent deux principes : initialise avant le consommateur le plus précoce possible et effectue un nettoyage final après la dernière opération susceptible de recréer l’état. La réinitialisation d’un pointeur uniquement pendant un RINIT normal ou une étape d’arrêt antérieure peut manquer des accès antérieurs ou ultérieurs. S5

6.5 Pourquoi n’est-il pas recommandé d’effectuer votre propre « réparation en une seule ligne » ?

Remplacer tous les zend_bailout() par _exit(), ou simplement ajouter une vérification de pointeur nul à une certaine entrée, couvrirait un grand nombre de contextes d’exécution différents. Ils peuvent omettre d’autres champs d’état, ou modifier la destruction, les rappels étendus, l’hébergement de processus et la sémantique de fin de demande.

Pour les versions prises en charge, les correctifs complets déjà publiés sont prioritaires. La migration des propres branches doit enregistrer la source des correctifs, les lignes de base applicables, la gestion des conflits et les changements de comportement, et utiliser les cas d’utilisation de régression en amont correspondants et la vérification de ce processus métier. Les suggestions ici proviennent d’une analyse de la portée du correctif à travers les modifications de l’allocateur, du VM, de la session et du cycle de vie des demandes. S4S5

7. Rétroportage d’urgence de PHP 7.4, 8.0, 8.1

PHP fournit officiellement le rétroport minimum du code source de trois anciennes branches en fonction de la gravité. Les noms des succursales sont :

PHP-7.4-CVE-2026-109618-109619
PHP-8.0-CVE-2026-109618-109619
PHP-8.1-CVE-2026-109618-109619

Pour les liens de branche, voir S7S8S9. Il s’agit de livraisons d’urgence pour cette vulnérabilité et ne représentent pas un retour au support régulier en amont de l’ancienne branche, ni ne remplacent d’autres mises à jour de sécurité. S1

7.1 Prenons l’exemple du rétroportage PHP 8.1

Les soumissions pertinentes pour PHP 8.1 sont :

1d7dec178a094e6e75b229ce22754045f8c6070a

Sa stratégie privilégie la rapidité d’échec : appeler _exit(1) après avoir généré des diagnostics dans le chemin OOM correspondant, et incluant l’état global et d’autres corrections pertinentes ; tout en désactivant en interne le traitement correspondant de la progression du téléchargement de session. Pour la soumission du code source pertinent, voir S6.

Il s’agit d’une différence de comportement par rapport à la conception OOM retardée plus complète dans la branche prise en charge. Ce n’est pas parce que la configuration indique toujours que la progression du téléchargement est activée que le comportement du traitement interne après ce rétroportage restera inchangé.

7.2 Le prix que vous devez accepter lors du déploiement

Quitter directement le processus peut entraîner l’échec de la requête en cours, ignorer les rappels d’arrêt normaux de PHP et une partie de la fermeture de l’application ; si l’hôte adopte un modèle de thread, il est également nécessaire d’évaluer l’impact de la sortie de l’ensemble du processus hôte sur les autres travaux simultanés. La question de savoir si le gestionnaire de processus peut mettre en œuvre le processus de remplacement à temps doit également être incluse dans la vérification.

Par conséquent, les utilisateurs d’anciennes versions doivent considérer dans l’ordre :

  1. Migrez vers la branche PHP prise en charge et sa version fixe.
  2. Utilisez une version qui couvre explicitement à la fois la mise à jour du fabricant CVE ou LTS.
  3. S’il est effectivement soumis à l’ancienne version du code source, utilisez le rétroport d’urgence officiel de la version correspondante pour vérifier les modifications complètes et la compatibilité, et organiser une migration ultérieure.

Le « backport minimum » décrit ici la compatibilité et la portée de mise en œuvre sélectionnées par le responsable, et ne doit pas être automatiquement interprété comme « des correctifs de vulnérabilités incomplets connus ». Vous devez juger en fonction du code source de la branche correspondante et de l’annonce du fabricant, et ne pas supprimer vous-même les modifications prises en charge. S1S6

8. Critères d’acceptation et inspections de suivi

Il est recommandé d’utiliser les résultats suivants comme base pour effectuer cette réparation :

Articles d’acceptationNormes d’achèvement
couverture des vulnérabilitésL’annonce de build ou du fournisseur corrige explicitement CVE-2026-109618 et CVE-2026-109619.
Couverture du déploiementTous les portails, pools, services et répliques utilisent le runtime réparé
Le processus prend effetL’ancien travailleur, l’ancien processus hôte et l’ancien conteneur quittent tous
Vérification de la demande authentiqueSAPI confirmé, construit et configuré avec le lien Web réel pour éliminer les erreurs de direction du cache
disponibilité commercialeLes fonctions clés telles que la session, le téléchargement, l’importation et la gestion des erreurs sont revenues normalement.
Fin des mesures temporairesLes configurations de mémoire illimitée et de recyclage extrême des travailleurs ont été restaurées conformément au plan de capacité ou ont une raison claire de conservation
Preuve de changementEnregistrer la version du package ou le résumé de l’image, la portée de la mise à jour, l’heure d’achèvement et les résultats de la vérification

Ce qui précède sont des suggestions de mise en œuvre. Si vous devez vérifier le comportement de OOM, une sortie anormale ou des correctifs personnalisés, vous devez utiliser des tests de régression en amont ou une injection de fautes contrôlée dans un environnement isolé pour éviter de créer de manière répétée un épuisement de la mémoire dans l’environnement de production comme méthode d’acceptation.

Vérifiez également les événements fatals PHP, les accidents de travail, les redémarrages anormaux, le taux d’erreur de demande et les événements WAF avant et après la mise à jour. Les journaux ne peuvent fournir que des indices d’investigation : l’apparition de OOM ne signifie pas qu’il a été exploité, et l’absence d’alarmes ne prouve pas qu’aucune exploitation n’a eu lieu. La mise à niveau corrige les chemins de vulnérabilité qui pourraient être atteints à l’avenir ; si des anomalies telles qu’une falsification de fichiers ou une fuite d’informations d’identification sont constatées, des enquêtes distinctes sur les incidents doivent être menées.

Annexe : sources citées et liens

Tous les liens sources sont rassemblés ci-dessous. Les avis, correctifs et conseils du fournisseur reflètent les vérifications effectuées en date du O22 octobre 2026 ; les déploiements ultérieurs doivent vérifier les mises à jour des fournisseurs. Les citations numérotées dans le texte font référence à ces entrées.

S1 — Bulletin de sécurité officiel PHP et version de réparation

  • Source : Projet PHP, 21 octobre 2026.
  • Objectif : étendue des risques, quatre versions de réparation officielles, mesures temporaires officielles et instructions de rétroportage d’urgence pour les anciennes succursales.
  • Référence: PHP 2026 This security bulletin est dans les archives du bulletin annuel

S2 — Bulletin technique officiel CVE-2026-109618

  • Source : php/php-src GitHub Security Advisory, 21 octobre 2026.
  • Identification : GHSA-w8hw-w9fx-j79w.
  • Objectif : Limite de couverture pour OOM, amplification en plusieurs parties, différence et atténuation SAPI.
  • Référence: RCE via OOM corruption

S3 — Bulletin technique officiel CVE-2026-109619

  • Source : php/php-src GitHub Security Advisory, 21 octobre 2026.
  • Identification : GHSA-6wmf-4rv5-p3rp.
  • Objectif : état en suspens de requêtes croisées, producteurs et consommateurs, initialisation précoce, atténuation de la configuration.
  • Référence: RCE via stale global state

S4 — Soumission officielle du correctif PHP 8.5

  • Source : php/php-src.
  • Soumettre : 31c0ea7d7ff1d1fccb6492e52dab544011628065.
  • Objectif : Confirmer la soumission formelle pour corriger deux vulnérabilités en même temps et expliquer l’orientation globale du changement.
  • Référence: Avoid state corruption via bailout

S5 — PHP 8.5 Officiellement restauré et différentiel complet

  • Source : différent de la même soumission officielle.
  • Objectif : Vérifier l’implémentation spécifique de l’allocateur, VM, HTTP globals, la session, la sérialisation et le cycle de vie des demandes.
  • Référence: official complete diff

S6 — Soumission officielle de rétroportage d’urgence de PHP 8.1

S7 — Branche officielle de backport d’urgence PHP 7.4

  • Source : branches de code source php/php-src, PHP répertoriées dans le bulletin de sécurité officiel.
  • Référence: PHP-7.4-CVE-2026-109618-109619

S8 — Branche officielle de backport d’urgence PHP 8.0

  • Source : branches de code source php/php-src, PHP répertoriées dans le bulletin de sécurité officiel.
  • Référence: PHP-8.0-CVE-2026-109618-109619

S9 — Branche officielle de backport d’urgence PHP 8.1

  • Source : branches de code source php/php-src, PHP répertoriées dans le bulletin de sécurité officiel.
  • Référence: PHP-8.1-CVE-2026-109618-109619

S10 — Bulletin de sécurité Ubuntu USN-8948-1

  • Source : Canonical / Ubuntu, 21 octobre 2026.
  • Objectif : publier un rétroportage et compléter des exemples de versions de packages.
  • Référence: USN-8948-1: PHP vulnerabilities

S11 — Manuel PHP-FPM Configuration

  • Source : document officiel PHP.
  • Objectif : sémantique de configuration telle que php_admin_value, php_admin_flag, pm.max_requests, etc.
  • Référence: PHP-FPM Configuration

S12 — Manuel de configuration du noyau PHP INI

  • Source : document officiel PHP.
  • Objectif : Définition et portée du corps de la demande, du téléchargement, de la mémoire et de la configuration de la lecture automatique POST.
  • Référence: Description of core php.ini directives

S13 — Nginx demande la limite de taille du corps

S14 — Tampon de requête Nginx FastCGI

S15 — Nginx Condition et instructions de retour

  • Source : document officiel Nginx.
  • Objectif : Syntaxe de configuration de if et return.
  • Référence: ngx_http_rewrite_module

S16 — Instructions de protection Cloudflare PHP2Shell