↓ Aller au contenu

PHP : correctifs disponibles pour deux failles critiques de RCE

··1745 mots·9 mins
Cryptolab.re
Auteur
Cryptolab.re
Cryptolab est un blog personnel où je documente mes expérimentations techniques : infra, self-hosting, réseau, crypto et projets parfois inutiles, souvent instructifs.
Sommaire

PHP a publié les correctifs des deux failles critiques annoncées cette semaine. Les versions 8.2.35, 8.3.36, 8.4.27 et 8.5.12 sont disponibles, ainsi que les paquets Debian 12 et 13. L’exécution de code sans authentification est démontrée sur mod_php et, avec certaines applications, sur PHP-FPM : les serveurs web concernés ont une mise à jour à faire.

Les paquets sont là, sur Debian et Ubuntu
#

Les deux vulnérabilités, CVE-2026-109618 et CVE-2026-109619, sont notées 9,2 en CVSS v4.0. Voici les versions à installer pour les branches maintenues par PHP :

BrancheVersions affectéesVersion corrigée
8.2Avant 8.2.358.2.35
8.3Avant 8.3.368.3.36
8.4Avant 8.4.278.4.27
8.5Avant 8.5.128.5.12

Sur Debian, les révisions corrigées sont également connues :

DistributionPaquet corrigéAvis
Debian 12 Bookworm8.2.35-1~deb12u1DLA-4848-1
Debian 13 Trixie8.4.27-1~deb13u1DSA-6574-1

Les deux figurent dans les index amd64 de bookworm-security et trixie-security, vérifiés le 21 octobre à 23 h 54, heure de Paris. Le décalage de publication observé sur Bookworm dans l’après-midi est résolu.

Ondřej Surý a aussi livré les correctifs dans son PPA Ubuntu ondrej/php, pour les branches PHP 5.6 à 8.5. Les paquets amd64 sont disponibles pour Ubuntu 22.04 Jammy et 24.04 Noble. Les changelogs des anciennes branches confirment le rétroportage des deux correctifs, y compris pour PHP 5.6. Un sacré boulot de maintenance pour les applis qui n’ont pas encore quitté leurs vieux PHP.

Sur Debian, son dépôt est Sury : même mainteneur, paquets construits pour une autre distribution. Pour PHP 7.4, la révision 1:7.4.33-31 intègre les deux correctifs, comme l’indique son changelog Debian. Le seul numéro 7.4.33 ne permet donc pas de savoir où vous en êtes. Pour une fois, on a une bonne raison de lire le suffixe du paquet jusqu’au bout.

PHP 8.1 et les branches antérieures ne reçoivent plus de nouvelles versions du projet. PHP a toutefois publié des correctifs sources pour 7.4, 8.0 et 8.1. Leur installation dans un paquet dépend du fournisseur ; la migration vers une branche maintenue reste à prévoir.

Ce qui casse dans PHP
#

Les deux failles concernent la mémoire et la manière dont PHP termine une requête. Elles peuvent donner à un attaquant les droits du processus qui sert les pages. PHP vise l’ensemble des installations web, dont mod_php, FPM, CGI, FrankenPHP et LiteSpeed. Les démonstrations les plus directes concernent mod_php, avant même l’exécution du script demandé. La page de connexion n’a pas encore eu son mot à dire.

CVE-2026-109618 : un manque de mémoire mal géré
#

Dans les versions vulnérables, un manque de mémoire provoque un longjmp(), qui interrompt l’opération en cours. Si PHP était en train d’initialiser une structure, celle-ci peut rester accessible dans un état incomplet. Lors de la fermeture de la requête, le moteur la traite pourtant comme une donnée valide.

Une requête multipart peut provoquer cet épuisement en multipliant les en-têtes, les métadonnées de fichiers ou les tableaux imbriqués. Leur représentation en mémoire coûte davantage que les octets reçus. Certains corps sans longueur déclarée utilisable passent aussi le contrôle initial de post_max_size. Un petit upload sur le réseau peut ainsi occuper beaucoup de place une fois analysé.

PHP a validé une RCE par HTTP sur mod_php, avec les limites habituelles et plusieurs workers. Le worker FPM se termine si le démarrage de la requête échoue, ce qui arrête ce premier scénario. FPM reste exposé après un démarrage réussi selon l’analyse du code, sans exploit complet démontré pour cette CVE. Le correctif change la gestion de l’épuisement mémoire pour éviter cette fermeture sur des données mal initialisées.

CVE-2026-109619 : la requête suivante récupère un pointeur périmé
#

Ici, un worker garde une référence vers de la mémoire appartenant à une requête terminée. Cette mémoire a été libérée, mais une opération de la requête suivante utilise encore le pointeur avant sa remise à zéro. C’est une utilisation de mémoire libérée, ou use-after-free.

Le scénario décrit par PHP se déroule en plusieurs temps :

  1. Une requête laisse un état interne non nettoyé. Une erreur fatale peut interrompre le nettoyage ; un diagnostic tardif peut aussi recréer cet état après son nettoyage.
  2. Le moteur libère la mémoire de la requête, tandis que le worker conserve le pointeur.
  3. Une autre requête arrive sur le même worker et utilise ce pointeur trop tôt.
  4. Avec un agencement mémoire préparé pour cela, l’attaquant obtient une exécution de code.

Les chemins confirmés passent par des diagnostics INI précoces et par le suivi de progression des uploads. PHP a validé une RCE sur mod_php et sur FPM pour le cycle des sessions. Sur FPM, la première requête doit laisser cet état pendant l’exécution de l’application, puis rencontrer une erreur fatale. Un upload ultérieur réutilise le pointeur. Les opérations proposées par l’application comptent donc dans l’exploitabilité.

Ces démonstrations établissent le risque. Elles ne constituent pas, à elles seules, un signalement d’attaques en circulation.

Mettre à jour le PHP qui sert les pages
#

Le piège classique, c’est un php -v rassurant dans le terminal alors que le site utilise un autre pool FPM. PHP sait très bien cohabiter avec lui-même.

Sur Debian ou Ubuntu avec systemd, ces commandes permettent de repérer les versions installées et les services actifs. Elles ne modifient rien et ne demandent pas de droits administrateur :

php -v
dpkg-query -W -f='${db:Status-Status}\t${binary:Package}\t${Version}\n' '*php*'
systemctl list-units --type=service --state=running 'php*-fpm.service'

Dans la liste des paquets, gardez les lignes installed et leur révision complète. La commande systemd cherche les services FPM en cours ; elle ne couvre pas le module PHP d’Apache ni les conteneurs. Pour chaque site, le socket FPM déclaré dans le serveur web, le module Apache ou le panneau de l’hébergeur indique quel PHP travaille réellement.

Si vous utilisez les paquets d’une distribution, comparez leur révision à son avis de sécurité. Un fournisseur peut intégrer le correctif sans reprendre le dernier numéro amont : c’est le principe des rétroportages expliqués par Debian. Le cas de Sury 7.4.33 en est un bon rappel.

Après installation des paquets corrigés, redémarrez le service FPM ou Apache concerné pour remplacer les anciens processus. Prévoyez l’interruption possible des requêtes en cours. Sur un hébergement mutualisé, demandez à l’hébergeur la révision déployée et l’heure du changement.

Pour Docker, le PHP de l’hôte ne met pas à jour celui des images. Avec un compte autorisé à utiliser Docker :

docker ps --format 'table {{.Names}}\t{{.Image}}'
docker exec NOM_DU_CONTENEUR php -v

Remplacez NOM_DU_CONTENEUR par le nom relevé. Si le binaire CLI est absent de l’image, consultez sa documentation et ses notes de version. Il faut récupérer une image corrigée ou reconstruire la vôtre, puis recréer le conteneur. Un docker pull télécharge la nouvelle image. Le conteneur en cours garde l’ancienne jusqu’à sa recréation.

Une fois les nouveaux processus en place, vérifiez les parcours qui comptent pour votre application : connexion, upload, tâches planifiées. Et si vous soupçonnez déjà une compromission, la mise à jour ne fera pas disparaître un webshell. Huntress conseille de rechercher les shells et outils inhabituels lancés par PHP ; des fichiers PHP modifiés ou des tâches planifiées inattendues sont aussi à examiner. Ces indices restent génériques, et leur absence ne prouve pas que le serveur est sain. En présence de signes concordants, isolez le service et préservez les traces.

Si le déploiement doit attendre
#

Les paquets existent maintenant. S’il vous faut encore du temps pour les déployer, une restriction d’accès au frontal ou au réseau peut retirer temporairement PHP de l’Internet public, comme le suggère le CERT-EU. Le bouton « maintenance » du CMS n’est pas un interrupteur pour PHP : servez une page statique sans transmettre les requêtes au moteur si vous voulez couper ce traitement.

PHP propose aussi des réglages temporaires pour réduire l’exposition pendant l’attente. La mise à jour reste nécessaire pour couvrir les deux failles :

  • CVE-2026-109618 : imposer memory_limit=-1 retire le seuil PHP qui permet de provoquer l’épuisement contrôlable. Un échec d’allocation système peut encore atteindre le code vulnérable. Les limites au frontal doivent couvrir la taille décodée, les champs, les parties multipart, les en-têtes et la profondeur, y compris sans Content-Length utilisable.
  • CVE-2026-109619, chemin session : session.upload_progress.enabled=0 coupe le suivi d’upload concerné. Le réglage doit s’appliquer avant l’analyse de la requête, dans php.ini, le pool FPM ou la configuration serveur. ini_set() et .user.ini sous FPM arrivent trop tard pour cette mesure.
  • PHP 8.5 : fatal_error_backtraces=0 bloque le chemin confirmé des backtraces fatales. Les autres états globaux ne sont pas couverts.

Attention au premier réglage : memory_limit=-1 enlève la limite de mémoire par script. Avant de l’appliquer, prévoyez une limite externe, par conteneur ou cgroup, pour contenir l’impact sur le serveur. Une limite commune peut arrêter le maître et tous ses workers. Aucun réglage de pool, de répertoire ou d’application ne doit rétablir une limite PHP finie. PHP déconseille RLIMIT_AS et RLIMIT_DATA, qui peuvent justement provoquer l’échec d’allocation vulnérable. La documentation de memory_limit et le bulletin détaillent ces points.

Ces changements nécessitent les droits d’administration et le redémarrage de tous les workers, avec interruption possible. Les valeurs administratives d’un pool FPM empêchent l’application de les remplacer avec ini_set(). Après vérification du PHP corrigé, rétablissez vos limites mémoire habituelles.

Enfin, bloquer multipart/form-data au niveau d’un WAF ferme cette entrée, au prix des formulaires qui l’utilisent. Les autres chemins applicatifs restent en jeu : cela ne remplace pas le correctif. Avec Cloudflare, vérifiez aussi que l’origine refuse les accès directs, sinon la règle ne voit même pas passer la requête. La documentation Cloudflare décrit les moyens de l’imposer.

Sources
#

Visuel : logo PHP de Colin Viebrock, sous licence CC BY-SA 4.0. Couverture adaptée par centrage sur un fond uni et conversion en WebP, sous la même licence.

Articles connexes

Dirty Frag sous Linux : vérifier l'exposition et installer les correctifs

··1359 mots·7 mins
Dirty Frag désigne deux vulnérabilités du noyau Linux publiées le 7 mai 2026 par Hyunwoo Kim. Elles sont suivies sous CVE-2026-43284 pour le chemin XFRM/ESP et CVE-2026-43500 pour RxRPC. Dans les deux cas, un attaquant qui peut déjà exécuter du code localement peut modifier une page du cache mémoire associée à un fichier normalement accessible en lecture seule. Le démonstrateur public utilise cette primitive pour obtenir les privilèges root. Mise à jour du 28 août 2026 : les deux CVE disposent désormais de correctifs dans les noyaux fournis par les principales distributions. La désactivation des modules reste une solution temporaire lorsque la mise à jour est impossible. L’article initial, écrit pendant la divulgation, indiquait encore que le second correctif n’était pas publié.

GitHub Actions : empêcher l'empoisonnement du cache avec cache-mode

Un cache CI est souvent considéré comme un simple réglage de performance. Pourtant, les fichiers restaurés peuvent finir dans un chemin exécuté par le build : dépendances, scripts, objets compilés, outils téléchargés ou couches intermédiaires. Un cache modifié par un job peu fiable peut donc devenir un canal d’exécution dans un workflow plus privilégié. Depuis le 10 septembre 2026, GitHub Actions permet de fixer explicitement les droits du cache avec cache-mode. La clé accepte quatre valeurs, read, write, write-only et none, au niveau du workflow ou d’un job. La fonction est disponible sur github.com pour tous les plans. Le réglage le plus utile en pratique consiste à séparer les rôles : les validations de pull requests restaurent un cache en lecture seule, tandis qu’un workflow déclenché depuis une branche de confiance produit les nouvelles entrées. Les jobs de publication qui n’ont pas besoin du cache le désactivent complètement. cache-mode impose une limite de droits appliquée par le service de cache. Il ne vérifie toutefois pas l’intégrité des fichiers déjà présents et ne corrige pas un workflow qui exécute du code non fiable avec des secrets.