Aller au contenu principal

Failles critiques dans PHP : ce que CVE-2026-109618 et CVE-2026-109619 changent pour ton serveur

Deux failles notées 9,2 sur 10 permettent d'exécuter du code à distance sur un serveur PHP, sans compte ni mot de passe. Cet article explique leur mécanisme sans jargon, compare l'exposition de mod_php, PHP-CGI et PHP-FPM, puis donne les commandes pour vérifier ta version, mettre à jour et appliquer les contournements officiels.

Sécurité ·
Adel LATIBI
Adel LATIBI

Le Briefing Dev - les ressources et actus de la semaine, droit dans ta boîte chaque vendredi gratuitement.

En vous inscrivant, vous acceptez de recevoir notre newsletter. Désinscription possible à tout moment.

Le 21 octobre 2026, le projet PHP a publié quatre versions correctives le même après-midi, accompagnées d'un bulletin dont le titre demande de mettre à jour tout de suite. Le CERT-FR, le centre d'alerte de l'ANSSI, a relayé l'information dans la foulée sous la référence CERTFR-2026-ALE-014.

Entre lire une alerte et savoir quoi changer sur son propre serveur, il y a un écart. Les avis techniques parlent de SAPI, de workers, de use after free et de longjmp(). Une personne en reconversion qui a mis son premier projet Symfony sur un VPS, un développeur junior qui maintient le WordPress d'un client ou un curieux qui héberge le site d'une association lit ces mots sans pouvoir en déduire si sa machine est concernée.

L'information officielle est exacte et complète, mais elle s'adresse d'abord aux personnes qui maintiennent PHP. Il manque le passage vers deux questions pratiques : ma configuration est-elle exposée, et que dois-je modifier, y compris si la mise à jour doit attendre quelques jours.

Cet article fait ce passage à partir des sources officielles, commandes comprises. Au moment où ces lignes sont écrites, le 22 octobre 2026, les versions corrigées sont PHP 8.5.12, 8.4.27, 8.3.36 et 8.2.35. Les exemples de configuration ciblent ces versions.

Ce qui a été publié les 20 et 21 octobre 2026

Le 20 octobre, l'équipe sécurité de PHP a prévenu qu'une publication de sécurité sortirait le lendemain à 14h00 UTC, pour deux vulnérabilités critiques notées 9,2 sur l'échelle CVSS v4.0. Le 21 octobre, les correctifs sont sortis avec les détails techniques.

Les deux failles portent le même impact : un attaquant non authentifié peut exécuter du code sur le serveur avec les droits du compte qui fait tourner PHP. Sur un serveur Debian ou Ubuntu installé avec les paquets standards, ce compte est souvent www-data, qui lit les fichiers du site et donc les identifiants de la base de données.

Branche Vulnérable Corrigée Remarque
8.5avant 8.5.128.5.12Branche la plus récente
8.4avant 8.4.278.4.27
8.3avant 8.3.368.3.36
8.2avant 8.2.358.2.35Fin de support le 31 décembre 2026
8.1 et antérieurestoutesaucune version officielleCorrectifs sources minimaux pour 7.4, 8.0 et 8.1

Le bulletin de php.net liste les installations à risque : toutes celles qui servent des requêtes web, avec PHP-FPM, Apache et mod_php, php-cgi, FrankenPHP et LiteSpeed cités nommément. Il précise que le risque le plus élevé concerne mod_php. L'alerte du CERT-FR, elle, recommande d'isoler les équipements touchés puis de migrer vers une version maintenue et corrigée.

Détail utile pour Red Hat, Rocky ou Alma : selon le bulletin, le dépôt bénévole rpms.remirepo.net n'avait pas de mise à jour le jour de la publication, et l'équipe PHP conseille de passer aux paquets de la distribution.

Ces deux failles se trouvent dans l'interpréteur PHP lui-même. Un code applicatif bien écrit ne suffit pas à les fermer. Les bonnes pratiques détaillées dans l'article OWASP Top 10 2025 : une ligne de code fautive par catégorie restent nécessaires pour tout le reste, mais ici la correction passe par le serveur.

Le principe : un processus PHP qui garde de mauvais souvenirs

Pour comprendre les deux failles, il faut une notion : le worker. C'est un processus PHP qui reste en vie et traite des requêtes HTTP les unes après les autres. Chaque requête reçoit sa propre zone de mémoire, libérée à la fin. Le worker, lui, garde quelques informations globales d'une requête à la suivante : état des erreurs, des sessions, de certaines extensions.

CVE-2026-109619 : l'état global périmé

Certaines opérations écrivent dans ces variables globales une référence vers la mémoire de la requête en cours. Si la requête s'arrête brutalement avant le nettoyage, par une erreur fatale, un dépassement de mémoire ou un Maximum execution time exceeded, la mémoire est libérée mais la référence reste. On parle de use after free : du code utilise une zone mémoire déjà rendue, que d'autres données ont pu occuper entre-temps.

L'avis GHSA-6wmf-4rv5-p3rp décrit la chaîne en deux temps. Une première requête joue le rôle de producteur et laisse la référence périmée. Une seconde, traitée par le même worker, joue le rôle de consommateur et lit cette référence avant que PHP n'ait réinitialisé son état. Avec une mémoire préparée avec soin, l'attaquant obtient l'exécution de code.

Un seul worker PHP, deux requêtes successives Requête 1 écrit une référence dans l'état global puis erreur fatale Mémoire libérée la référence globale pointe toujours vers cette zone Requête 2 lit la référence avant la réinitialisation mémoire contrôlable
Le mécanisme producteur et consommateur décrit dans l'avis GHSA-6wmf-4rv5-p3rp.

Deux consommateurs ont été confirmés. Le premier est un simple avertissement émis pendant l'application d'une configuration par requête, avant l'initialisation normale : une directive obsolète ou invalide passée par un .htaccess sous mod_php, ou par les paramètres PHP_VALUE et PHP_ADMIN_VALUE qu'un nginx peut envoyer à FPM. L'état global est lu avant que PHP ne décide d'afficher ou non l'avertissement, donc l'opérateur @ ou display_errors = Off ne protègent de rien.

Le second consommateur est la fonction de suivi de progression des envois de fichiers, session.upload_progress. La documentation PHP précise qu'elle écrit dans la session avant l'exécution de tout script. L'avis ajoute qu'elle est active par défaut et qu'aucun appel à session_start() n'est nécessaire côté application pour qu'elle serve de point d'entrée.

CVE-2026-109618 : la corruption au moment du manque de mémoire

Quand une requête dépasse memory_limit, PHP abandonne le traitement en sautant directement vers la sortie, grâce à la fonction C longjmp(). Si ce saut arrive pendant qu'une structure interne est à moitié construite, la procédure de fin de requête la traite ensuite comme valide. L'avis GHSA-w8hw-w9fx-j79w montre que cette situation se provoque de façon reproductible, jusqu'à l'exécution de code.

Le moyen le plus simple d'y arriver passe par les formulaires multipart/form-data, ceux qui servent à envoyer des fichiers. L'avis cite plusieurs astuces qui restent sous post_max_size tout en épuisant la mémoire : un nombre illimité d'en-têtes dans une partie du formulaire, des champs de fichier vides qui ne comptent pas dans max_file_uploads, ou une requête sans taille déclarée exploitable. Le correctif supprime le saut brutal : PHP s'arrête désormais au prochain point sûr de la machine virtuelle, et tue le processus avec _exit() si la consommation atteint un second seuil plus haut.

mod_php, PHP-CGI, PHP-FPM : qui est exposé et pourquoi

PHP ne parle pas directement au navigateur. Un serveur web comme Apache ou nginx reçoit la requête et la transmet à PHP par une interface appelée SAPI (Server API). Les deux failles demandent soit une requête interrompue au mauvais moment, soit deux requêtes successives traitées par le même processus. Chaque SAPI gère ces deux situations à sa façon.

mod_php : PHP chargé dans Apache

Avec mod_php, l'interpréteur vit dans les processus d'Apache, qui traitent les requêtes à la suite. Selon l'avis sur CVE-2026-109618, mod_php lance toujours la procédure de fin de requête, même quand le démarrage de la requête a échoué. Le dépassement de mémoire peut donc survenir pendant la lecture automatique du corps du formulaire, avant la moindre ligne de ton application. Les deux exécutions de code ont été confirmées sur mod_php avec les limites par défaut, et php.net le désigne comme le cas le plus risqué.

PHP-CGI : un binaire lancé par le serveur web

Dans sa forme historique, le serveur web lance le binaire php-cgi à chaque requête. Ce binaire sait aussi fonctionner en FastCGI et réutiliser ses processus, avec des réglages que la documentation de FPM présente comme les équivalents des variables PHP_FCGI_CHILDREN et PHP_FCGI_MAX_REQUESTS. Les avis ne détaillent pas de scénario propre à php-cgi, et le bulletin de php.net le range parmi les installations à risque.

Cette configuration a déjà été visée en juin 2024 par CVE-2024-4577, une injection d'arguments propre à PHP-CGI sous Windows avec Apache, signalée comme activement exploitée par le CERT-EU. Les deux affaires n'ont pas de lien technique, mais un serveur php-cgi resté sans mise à jour depuis 2024 cumule les deux expositions.

PHP-FPM : un gestionnaire de processus séparé

FPM fait tourner un processus maître et un groupe de processus enfants, le pool, auquel nginx ou Apache passent les requêtes. La directive pm.max_requests vaut 0 par défaut : un enfant n'est jamais recyclé, la condition « même processus pour deux requêtes » est remplie. Quand le démarrage d'une requête échoue, FPM tue l'enfant concerné, ce qui coupe le chemin utilisé sur mod_php. D'autres chemins restent ouverts : pour CVE-2026-109619, une exécution de code via le suivi de progression des envois a été validée sur FPM, à condition que l'application offre une opération adaptée, et la configuration transmise par PHP_VALUE peut servir de déclencheur. Pour CVE-2026-109618, l'analyse du code conclut que FPM est vulnérable, sans exploitation complète démontrée.

SAPI CVE-2026-109618 (mémoire) CVE-2026-109619 (état périmé)
mod_phpExploitation confirmée, sans code applicatifExploitation confirmée
PHP-FPMVulnérable selon l'analyse du code, pas d'exploit complet publiéExploitation validée, dépend d'une opération de l'application
php-cgiListé comme exposé par php.net, pas de scénario détaillé dans les avis

Les différences entre SAPI portent sur le chemin d'attaque. La réponse reste la même pour les trois : mettre à jour, et appliquer les contournements en attendant si la mise à jour doit patienter.

Corriger ou contourner : les commandes, dans l'ordre

Étape 1 : savoir ce qui tourne réellement

La commande php -v donne la version de PHP en ligne de commande, qui peut différer de celle qui sert le site. Sur Debian et Ubuntu, plusieurs versions cohabitent souvent. Vérifie chaque binaire, puis le SAPI vu depuis le web :

# Version de la ligne de commande
php -v
 
# Version de PHP-FPM (nom du binaire sur Debian et Ubuntu)
php-fpm8.4 -v
 
# Apache charge-t-il mod_php ?
apachectl -M 2>/dev/null | grep -i php

Pour une réponse sans ambiguïté, dépose un fichier temporaire à la racine du site, appelle-le une fois depuis ton navigateur, puis supprime-le :

<?php
// verif-sapi.php : à supprimer juste après lecture
echo PHP_SAPI, ' ', PHP_VERSION;

Le résultat affiche par exemple fpm-fcgi 8.4.26. Les valeurs à reconnaître sont apache2handler pour mod_php, fpm-fcgi pour FPM et cgi-fcgi pour php-cgi.

Étape 2 : mettre à jour

Le bulletin indique que les distributions Linux et les éditeurs de support étendu ont reçu les correctifs en avance. Sur un VPS Debian ou Ubuntu, la mise à jour passe par le gestionnaire de paquets, suivie d'un redémarrage du service qui exécute PHP :

sudo apt update && sudo apt upgrade
 
# Avec PHP-FPM
sudo systemctl restart php8.4-fpm
 
# Avec Apache et mod_php
sudo systemctl restart apache2

Avec Docker, l'image officielle se récupère à nouveau et l'image de l'application se reconstruit, sinon le cache garde l'ancienne version. Contrôle ensuite le numéro affiché : s'il reste sous 8.4.27, l'image n'a pas encore été reconstruite en amont, et les contournements de l'étape 3 s'appliquent en attendant.

docker pull php:8.4-fpm
docker run --rm php:8.4-fpm php -v
 
# Reconstruire l'image de l'application en forçant le téléchargement de la base
docker build --pull -t mon-app .

Pour PHP 8.1 et les versions plus anciennes, le projet PHP ne publie plus de version. Trois voies existent : un correctif rétroporté par la distribution ou un éditeur de support étendu, les branches sources minimales publiées pour 7.4, 8.0 et 8.1 si tu compiles toi-même, ou la migration vers une branche maintenue. Si le passage à PHP 8 te semble flou, la formation PHP moderne : bases du développement côté serveur part des pratiques actuelles du langage, et l'article PHP est-il un vrai langage de programmation ? montre ce que PHP 8.5 permet aujourd'hui.

Étape 3 : si la mise à jour doit attendre

PHP et le CERT-FR le disent tous les deux : ces mesures ferment certains chemins d'attaque et laissent les autres ouverts. Le CERT-FR précise qu'il ne les a pas qualifiées.

Contre CVE-2026-109619, désactive le suivi de progression des envois, et sur PHP 8.5 les traces d'appel des erreurs fatales. Avec FPM, place ces lignes dans le fichier du pool, par exemple /etc/php/8.4/fpm/pool.d/www.conf sur Debian :

; Contournements provisoires, octobre 2026
php_admin_flag[session.upload_progress.enabled] = off
 
; PHP 8.5 uniquement
php_admin_value[fatal_error_backtraces] = 0

Les directives php_admin_* ne peuvent pas être modifiées par ini_set() depuis l'application. Sans FPM, la même chose se règle dans php.ini avec session.upload_progress.enabled = Off.

Repère aussi les configurations appliquées requête par requête, qui peuvent produire un avertissement avant l'initialisation. Supprime celles qui sont obsolètes ou déplace-les dans php.ini ou dans le pool :

# nginx qui transmet des réglages PHP à FPM
grep -rn "PHP_VALUE\|PHP_ADMIN_VALUE" /etc/nginx/
 
# Apache et .htaccess avec mod_php
grep -rn "php_value\|php_flag\|php_admin" /etc/apache2/ /var/www/ 2>/dev/null

Contre CVE-2026-109618, le bulletin propose de lever la limite mémoire propre à PHP, en la verrouillant pour que l'application ne la remette pas, et de garder des tailles de requête basses : 8 Mo si le site ne reçoit pas de fichiers, 32 Mo s'il en reçoit, avec upload_max_filesize en dessous de post_max_size :

; Pool FPM : limite PHP levée, à compenser par une limite du conteneur ou du cgroup
php_admin_value[memory_limit] = -1
php_admin_value[post_max_size] = 8M
php_admin_value[upload_max_filesize] = 6M

Si l'application n'accepte aucun envoi de fichier, le CERT-FR propose de bloquer les requêtes multipart en amont. Avec nginx, cela tient en deux lignes dans le bloc server :

client_max_body_size 8m;
 
if ($content_type ~* "multipart/") {
    return 415;
}

Redémarre ensuite tous les workers avec sudo systemctl restart php8.4-fpm ou apache2, et recharge nginx après sudo nginx -t. Si l'administration d'un serveur Linux reste nouvelle pour toi, l'article Mettre son projet en ligne : nom de domaine, VPS, HTTPS, déploiement reprend la chaîne complète, et la formation Linux et ligne de commande pour développeurs couvre les commandes utilisées ici.

Étape 4 : vérifier

Relance le fichier de l'étape 1. Pour un contournement, un second fichier temporaire suffit : var_dump(ini_get('session.upload_progress.enabled')); doit renvoyer une valeur vide ou "0". Supprime les deux fichiers ensuite, ils renseignent aussi un attaquant.

Les pièges qui laissent un serveur vulnérable

La plupart des erreurs viennent d'une vérification faite au mauvais endroit :

  • Lire php -v et s'arrêter là. La version en ligne de commande peut être corrigée pendant que FPM tourne sur une autre branche installée à côté.
  • Mettre à jour sans redémarrer. Les workers déjà lancés gardent l'ancien code en mémoire jusqu'à leur remplacement. Même chose pour un réglage changé dans le pool.
  • Comparer le numéro de version de la distribution à celui de php.net. Les distributions appliquent souvent le correctif sur leur propre numérotation. Le journal des modifications du paquet ou l'avis de sécurité de la distribution fait foi, pas le seul numéro.
  • Placer le contournement dans .user.ini ou via ini_set(). Le bulletin le dit explicitement : ces réglages arrivent trop tard, après le moment où la faille agit.
  • Couper le multipart sur un site qui reçoit des fichiers. La médiathèque d'un WordPress, un formulaire de candidature avec CV ou un import CSV cessent de fonctionner. L'article Développeur WordPress : sortir du thème acheté rappelle combien d'extensions s'appuient sur ces envois.
  • Passer memory_limit à -1 sans autre garde-fou. Une seule requête peut alors consommer toute la mémoire de la machine. Le bulletin recommande une limite de conteneur ou de cgroup en complément, et déconseille RLIMIT_AS et RLIMIT_DATA, qui déclenchent justement l'échec d'allocation vulnérable.
  • Compter sur les journaux pour se rassurer. L'avis sur CVE-2026-109619 précise qu'une absence d'erreur dans les logs ne prouve rien : l'échec peut survenir avant l'écriture du message.

Un dernier point concerne l'après-correctif. L'avis suggère de laisser session.upload_progress désactivé même une fois PHP à jour, si l'application ne s'en sert pas, parce que cette fonction peu utilisée et peu testée attire désormais l'attention des chercheurs. Pour les projets conteneurisés, la formation Docker pour développeurs web montre comment figer ces réglages dans l'image plutôt que de les reporter à la main sur chaque serveur.

Questions fréquentes

Mon site est chez un hébergeur mutualisé, suis-je concerné ?

Sur un hébergement mutualisé, l'hébergeur met PHP à jour. Vérifie la version dans ton espace client ou avec le fichier temporaire décrit plus haut. Si elle reste sous les versions corrigées après quelques jours, ouvre un ticket en citant CVE-2026-109618 et CVE-2026-109619, ou passe sur une branche plus récente si l'interface le permet.

Ces failles sont-elles déjà exploitées ?

Au 22 octobre 2026, ni le bulletin de php.net ni l'alerte du CERT-FR ne signalent d'exploitation constatée. Les détails techniques sont en revanche publics depuis le 21 octobre, ce qui raccourcit le temps dont dispose un attaquant pour écrire un outil. L'alerte du CERT-FR est la page à surveiller.

Désactiver session.upload_progress casse-t-il mon application ?

Seulement si elle affiche une barre de progression d'envoi qui lit les données de session prévues à cet effet par PHP. Les envois de fichiers eux-mêmes continuent de fonctionner. La documentation PHP note aussi que cette fonction marche mal derrière un serveur qui met en tampon les grosses requêtes, et cite nginx comme exemple.

Mon serveur tourne sous PHP 7.4, que faire ?

Le projet PHP ne publie plus de version pour cette branche. L'équipe sécurité a publié une branche source minimale pour 7.4 avec les deux correctifs, utile si tu compiles PHP toi-même. Sinon, vérifie si ta distribution ou un éditeur de support étendu fournit un paquet corrigé. Le CERT-FR recommande d'isoler la machine en attendant la migration vers une version maintenue.

Régler pm.max_requests à 1 suffit-il à se protéger ?

L'avis sur CVE-2026-109619 le cite comme une piste de réduction du risque, puisqu'un enfant FPM qui ne traite qu'une requête ne transmet aucun état à la suivante. Le coût en performance est élevé et la mesure ne couvre pas CVE-2026-109618.

Vous êtes expert ?

Partagez votre expertise sur notre blog

Tutoriel, retour d'expérience, analyse - publiez un article invité et gagnez en visibilité.

Écrire pour nous