PHP2Shell : deux failles critiques dans le runtime PHP
Le 21 octobre 2026, l'équipe PHP a publié en urgence quatre correctifs pour colmater CVE-2026-109618 et CVE-2026-109619, deux vulnérabilités de type heap use-after-free dans le gestionnaire session.upload_progress, activé par défaut depuis PHP 5.4. Leur score CVSS v4.0 atteint 9,2 sur 10 et elles permettent une exécution de code à distance (RCE) sans authentification. Toutes les SAPI sont concernées : le module Apache mod_php, PHP-FPM derrière un serveur web Nginx, php-cgi, FrankenPHP et LiteSpeed. L'attaque passe par un formulaire multipart malformé et atteint le parseur PHP avant que le code applicatif ne s'exécute : aucune couche d'authentification ne la bloque. Notre actualité détaille les CVE et les premières mesures : failles critiques PHP CVE-2026-109618 et 109619.
Ce tutoriel va plus loin : il couvre la partie Docker. Si vous administrez un CMS comme WordPress ou Nextcloud, un framework PHP tel que Laravel ou Symfony, ou n'importe quelle application connectée à une base de données MySQL ou PostgreSQL dans des conteneurs Docker, un simple docker restart ne corrige rien. Le conteneur relance le même runtime PHP vulnérable embarqué dans l'image. Il faut reconstruire l'image à partir d'un tag patché. Ce guide montre aux administrateurs comment auditer, corriger et durcir leurs conteneurs Docker PHP depuis un terminal SSH sur un VPS Linux ou un serveur dédié.
Versions concernées et versions patchées
Le tableau ci-dessous récapitule les branches PHP maintenues et leurs correctifs. Les versions antérieures à PHP 8.2 (8.1, 8.0, 7.x) sont en fin de vie et ne reçoivent pas de correctif officiel. Des backports source existent pour PHP 7.4, 8.0 et 8.1, mais leur intégration reste à la charge de l'administrateur ou du mainteneur de la distribution.
| Branche PHP | Dernière version vulnérable | Version patchée | Statut |
|---|---|---|---|
| PHP 8.5 | 8.5.11 et antérieures | 8.5.12 | Supportée (active) |
| PHP 8.4 | 8.4.26 et antérieures | 8.4.27 | Supportée (active) |
| PHP 8.3 | 8.3.35 et antérieures | 8.3.36 | Supportée (active) |
| PHP 8.2 | 8.2.34 et antérieures | 8.2.35 | Sécurité uniquement |
| PHP 8.1 et antérieures | Toutes | Aucun correctif officiel | Fin de vie |
Les images Docker officielles php:* du Docker Hub sont basées sur Debian ou Alpine. Les packages Debian (php8.x-fpm, php8.x-cli) et les packages Alpine (php84) intègrent le correctif par le numéro de version upstream ou par un backport mentionné dans le changelog du paquet. Si vos conteneurs utilisent une distribution comme Ubuntu, Debian ou Alpine, vérifiez que le package PHP installé cite le CVE dans son changelog : apt changelog php8.4-fpm sur Debian ou Ubuntu, apk info -a php84 sur Alpine.
Si vos conteneurs Docker embarquent encore PHP 8.1 ou une version antérieure, la migration vers une branche supportée est la seule solution pérenne pour les administrateurs.
Auditer vos conteneurs Docker PHP
Avant de corriger, il faut savoir ce qui tourne. Ouvrez un terminal SSH vers l'adresse IP de votre serveur et vérifiez que le daemon Docker est actif (systemctl status docker). Listez ensuite la version PHP de chaque conteneur :
docker ps --format "{{.Names}}" | while read c; do
echo "$c: $(docker exec "$c" php -v 2>/dev/null | head -1)"
doneCette commande affiche le nom du conteneur suivi de la version du runtime PHP embarqué. Comparez chaque résultat au tableau ci-dessus. Un conteneur qui n'a pas PHP (un conteneur MySQL, Redis ou Nginx seul) affiche une ligne vide : c'est normal. Si Docker n'est pas encore installé, consultez notre guide installer Docker sur un VPS.
Audit automatisé avec php2shell-check
Le projet open source php2shell-check (licence MIT, créé par MakFly) automatise l'audit sur l'hôte, en SSH et dans les conteneurs Docker. Ses scripts ne contiennent aucun code d'exploitation : c'est un outil en lecture seule.
git clone https://github.com/MakFly/php2shell-check.git
cd php2shell-check
sudo ./check.shLe script check.sh parcourt les packages système (deb, rpm, apk), les binaires PHP installés hors gestionnaire de paquets, les processus PHP actifs (via /proc) et les conteneurs Docker. Il interroge dynamiquement php.net pour connaître les versions corrigées de chaque branche (8.2 à 8.5) et détecte les branches en fin de vie. Chaque élément reçoit un marqueur :
- [OK] : version patchée ou changelog du package confirmant le correctif ;
- [VULN] : version vulnérable ou branche en fin de vie ;
- [??] : statut indéterminé (socket du daemon Docker inaccessible, version inconnue).
Pour scanner les Dockerfiles et les fichiers de configuration docker-compose.yml de vos projets :
./docker-scan.sh ~/projetsCe script identifie les images de base PHP, résout les variables ARG, classe les références (tag épinglé, tag flottant, digest figé) et affiche la version PHP de chaque image. Idéal pour les administrateurs qui gèrent plusieurs projets sur un même serveur.
Audit avec Docker Scout
Si vous utilisez Docker Scout, ciblez directement les deux CVE :
docker scout cves --only-cve-id CVE-2026-109618,CVE-2026-109619 mon-image:latestVérifier les logs pour détecter une exploitation
Les fichiers de log du serveur web (Apache ou Nginx) et les logs d'erreur PHP peuvent révéler des signes d'exploitation. Recherchez les erreurs Allowed memory size exhausted sur la ligne 0 d'un fichier inconnu (Unknown:0), des segfaults dans les workers du daemon PHP-FPM, ou des processus PHP qui engendrent un shell Unix :
# Logs du conteneur PHP-FPM
docker compose logs php | grep -i "memory\|segfault\|fatal"
# Logs du serveur web Nginx en reverse proxy
docker compose logs nginx | grep -i "502\|upstream"Pour un audit système plus poussé, consultez notre guide auditd sur VPS Linux.
Mitigation temporaire via le fichier de configuration PHP
Si vous ne pouvez pas reconstruire vos images Docker immédiatement, une mitigation temporaire consiste à désactiver le gestionnaire de progression des uploads dans le fichier de configuration php.ini. Ce réglage bloque le vecteur d'attaque principal de CVE-2026-109619 :
# Dans php.ini ou un fichier de configuration PHP additionnel (.ini)
session.upload_progress.enabled = 0Pour appliquer ce changement dans un conteneur Docker sans reconstruire l'image, montez un fichier de configuration personnalisé en volume dans votre docker-compose.yml :
# docker-compose.yml
services:
php:
image: php:8.4-fpm
volumes:
- ./php-mitigation.ini:/usr/local/etc/php/conf.d/99-mitigation.ini:roConfigurez également une limite de mémoire RAM stricte au niveau du conteneur pour réduire la surface d'attaque de CVE-2026-109618 (qui exploite un dépassement mémoire) :
services:
php:
deploy:
resources:
limits:
memory: 512MCes mesures ne remplacent pas le patch. Elles réduisent le risque en attendant la reconstruction de vos images. Les extensions PHP installées (OPcache, PDO, mbstring, GD, intl) ne sont pas affectées par cette configuration et continuent de fonctionner normalement.
Sauvegarder avant de patcher
Avant de reconstruire vos images Docker, sauvegardez les données persistantes. Un rebuild ne touche pas aux volumes Docker, mais un incident peut entraîner une perte de données. Sauvegardez en priorité :
- Les bases de données : exportez vos bases MySQL, MariaDB ou PostgreSQL avec
mysqldumpoupg_dumpavant toute opération (guide sauvegardes MySQL) ; - Les volumes Docker : fichiers uploadés par les utilisateurs, données de cache, fichiers de configuration applicatifs. Un
docker compose downsans l'option-vpréserve les volumes ; - Les fichiers de configuration :
docker-compose.yml, Dockerfiles, fichiers.env, configs Nginx ou Apache personnalisées.
Pour automatiser le backup de votre serveur, consultez notre guide sauvegarder un VPS avec rsync.
Mettre à jour vos images Docker PHP
Un redémarrage de conteneur (docker restart) ne corrige rien : le conteneur relance la même image avec le même binaire PHP vulnérable. Il faut reconstruire l'image depuis un Dockerfile corrigé.
1. Modifier le Dockerfile
Remplacez le tag de l'image de base par la version patchée correspondant à votre branche :
# Avant (vulnérable)
FROM php:8.4-fpm
# Après (version patchée)
FROM php:8.4.27-fpmUtilisez un tag exact (avec le numéro de patch) plutôt qu'un tag flottant comme 8.4-fpm. Le tag flottant finira par pointer vers la bonne version, mais sans garantie de délai. Le tag exact assure que chaque docker build produit une image contenant le correctif. Les extensions PHP installées via docker-php-ext-install (pdo_mysql, gd, opcache, intl, etc.) seront recompilées automatiquement lors du rebuild.
2. Reconstruire et redéployer
docker compose build --pull --no-cache
docker compose up -d --force-recreateL'option --pull force le téléchargement de la dernière version de l'image de base depuis le Docker Hub. L'option --no-cache empêche le daemon Docker de réutiliser un layer mis en cache contenant l'ancienne version. Si vous gérez vos stacks avec Docker Compose sur VPS Linux, cette commande suffit pour reconstruire l'ensemble de la stack.
Si vous utilisez Docker Desktop sous Windows, la procédure est identique : Docker exécute les conteneurs dans une machine virtuelle Linux via WSL 2 ou Hyper-V. Le Dockerfile et les commandes docker compose restent les mêmes.
3. Vérifier après déploiement
docker compose exec mon-service php -vLe numéro de version affiché doit correspondre à la colonne "Version patchée" du tableau : 8.5.12, 8.4.27, 8.3.36 ou 8.2.35. Vérifiez aussi que vos extensions PHP sont chargées :
docker compose exec mon-service php -mL'URL et le nom de domaine de votre application ne changent pas après le rebuild. La configuration réseau Docker (résolution DNS interne, ports exposés) est recréée automatiquement par docker compose up.
Patcher les stacks applicatives courantes
Chaque application PHP en conteneur a ses particularités. Voici les points d'attention pour les stacks les plus fréquentes sur un serveur web.
WordPress + MySQL + Nginx ou Apache
WordPress est le CMS le plus déployé en conteneur Docker. Une stack typique comprend un conteneur PHP-FPM (ou Apache avec mod_php), un conteneur MySQL ou MariaDB pour la base de données, et un conteneur Nginx en reverse proxy devant PHP-FPM. Mettez à jour le tag PHP dans le Dockerfile ou dans le champ image: du fichier docker-compose.yml. Les extensions PHP requises par WordPress (mysqli, gd, xml, mbstring, curl) sont incluses dans les images officielles.
Laravel + PHP-FPM + Nginx
Les applications Laravel utilisent PHP-FPM derrière un reverse proxy Nginx. Ce framework nécessite les extensions pdo_mysql (ou pdo_pgsql pour une base de données PostgreSQL), bcmath, ctype et tokenizer. Après le rebuild, videz le cache Laravel : docker compose exec app php artisan cache:clear. Pour configurer Nginx comme proxy, consultez notre guide Nginx reverse proxy sur VPS Linux.
Nextcloud + MariaDB ou PostgreSQL
Nextcloud est un CMS de cloud personnel souvent auto-hébergé par les administrateurs en conteneur. L'image officielle nextcloud:fpm embarque PHP-FPM et ses extensions. Mettez à jour vers la dernière version de Nextcloud qui inclut un runtime PHP patché. Sauvegardez le volume de données et la base de données (MariaDB ou PostgreSQL) avant le rebuild.
Pterodactyl (panel de serveurs de jeu)
Pterodactyl utilise PHP pour son panel web d'administration. Si vous l'avez conteneurisé, mettez à jour l'image PHP sous-jacente. Pour les installations classiques (hors Docker), consultez notre guide mettre à jour Pterodactyl. Les serveurs de jeu FiveM, Minecraft ou Rust hébergés via Pterodactyl ne sont pas directement concernés par PHP2Shell : seul le panel d'administration (le serveur web) l'est.
Épingler le digest de l'image
Un tag Docker peut être réécrit à tout moment par le mainteneur de l'image. Pour garantir qu'un déploiement en production utilise exactement l'image que vous avez testée, épinglez le digest SHA256 dans votre Dockerfile :
# Récupérer le digest de l'image
docker buildx imagetools inspect php:8.4.27-fpm --format '{{.Manifest.Digest}}'
# Épingler dans le Dockerfile
FROM php:8.4.27-fpm@sha256:<digest>Cet épinglage rend le build déterministe. Couplé à un outil comme Renovate ou Dependabot dans votre pipeline CI/CD, le digest est mis à jour automatiquement quand une nouvelle image est publiée sur le registre (Docker Hub, GitHub Container Registry ou un registre privé). Pensez-y pour sécuriser votre serveur dédié sur le long terme.
Durcir les conteneurs PHP
Patcher la version PHP corrige les CVE connues, mais un conteneur bien durci limite les dégâts en cas de prochaine faille. Voici les bonnes pratiques pour les administrateurs.
- Docker Hardened Images : Docker propose des images PHP renforcées sous licence Apache 2.0 (
dhi/php:8.4.27-fpmsur le Docker Hub), basées sur Debian ou Alpine, sans shell, sans gestionnaire de paquets, exécutées en utilisateur non root (UID 65532). Même si un attaquant obtient une RCE, il n'a ni/bin/shniaptpour pivoter. Les quatre branches patchées sont disponibles. - Utilisateur non root : dans votre Dockerfile, ajoutez
USER www-data(ou un utilisateur dédié) après l'installation des dépendances et des extensions PHP. - Read-only filesystem : lancez le conteneur avec
--read-onlyet montez uniquement les répertoires qui ont besoin d'écriture (/tmp, le cache applicatif). Un attaquant ne peut alors pas déposer de script malveillant sur le filesystem. - Limites de RAM : configurez
deploy.resources.limits.memorydans le fichierdocker-compose.yml. CVE-2026-109618 exploite un dépassement mémoire : une limite RAM stricte réduit la surface d'attaque. - Pas de capabilities inutiles : utilisez
--cap-drop=ALLet réactivez uniquement celles dont votre application a besoin. - Surveillance des processus : le script
watch.shde php2shell-check surveille les processus enfants de PHP et des serveurs web (Apache, Nginx). Si un processus PHP engendre un shell ou un outil réseau (curl,wget,nc), il lève une alerte dans les logs. Pour un monitoring complet de votre serveur, configurez Grafana et Prometheus.
Pour compléter le durcissement réseau, consultez nos guides sur nftables et le pare-feu, Fail2ban SSH et l'automatisation des mises à jour de sécurité pour que les prochains correctifs système soient appliqués sans intervention manuelle sur l'hôte.
Cas particulier : FrankenPHP
FrankenPHP embarque PHP sous forme de bibliothèque liée statiquement dans le binaire du serveur web Caddy. Mettre à jour PHP sur l'hôte ou dans un conteneur classique n'a aucun effet sur FrankenPHP : il faut reconstruire l'image avec une version PHP patchée. Le script frankenphp-selfbuild.sh de php2shell-check automatise cette opération :
./frankenphp-selfbuild.sh 8.4.27 trixie v1.13.1Les trois arguments sont la version PHP cible, la distribution Debian de base (Trixie = Debian 13) et la version de FrankenPHP. Vérifiez la version du runtime embarqué dans le terminal avec frankenphp php-server -v.
Automatiser la détection dans la CI/CD
Pour ne plus découvrir une version vulnérable en production, intégrez le contrôle dans votre pipeline. Le projet php2shell-repo-audit (disponible en CLI et en GitHub Action) parcourt vos Dockerfiles, fichiers Docker Compose, manifestes Kubernetes, fichiers de configuration CI et composer.json, puis classe chaque version PHP trouvée. Il reconnaît les tags Laravel Sail, WordPress et Drupal.
# En ligne de commande depuis un terminal
npx php2shell-repo-audit .
# Dans un workflow GitHub Actions
- uses: Amsozzer1/php2shell-repo-audit@v1Combinez cet audit avec Docker Scout ou Trivy pour scanner les CVE dans chaque image avant de la pousser vers votre registre. Si votre hébergeur fournit des serveurs avec Docker préinstallé, comme les VPS Linux ElypseCloud, vous pouvez exécuter ces scripts directement sur le serveur via un cron ou un job CI/CD. Après le nettoyage, pensez à purger les images Docker obsolètes pour libérer de l'espace disque.
FiveM
Minecraft
Rust
RedM
Hytale