Offre Durée limitée : -10% sur tout le site* avec le code WELCOME10

PHP2Shell : auditer et patcher ses conteneurs Docker PHP

Mis à jour le 26 octobre 2026 12 min de lecture 12 sections

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 PHPDernière version vulnérableVersion patchéeStatut
PHP 8.58.5.11 et antérieures8.5.12Supportée (active)
PHP 8.48.4.26 et antérieures8.4.27Supportée (active)
PHP 8.38.3.35 et antérieures8.3.36Supportée (active)
PHP 8.28.2.34 et antérieures8.2.35Sécurité uniquement
PHP 8.1 et antérieuresToutesAucun correctif officielFin 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)"
done

Cette 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.sh

Le 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 ~/projets

Ce 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:latest

Vé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 = 0

Pour 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:ro

Configurez é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: 512M

Ces 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 mysqldump ou pg_dump avant 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 down sans l'option -v pré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-fpm

Utilisez 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-recreate

L'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 -v

Le 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 -m

L'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-fpm sur 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/sh ni apt pour 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-only et 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.memory dans le fichier docker-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=ALL et réactivez uniquement celles dont votre application a besoin.
  • Surveillance des processus : le script watch.sh de 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.1

Les 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@v1

Combinez 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.

Questions fréquentes

FAQ

Un simple redémarrage de conteneur Docker corrige-t-il la faille PHP2Shell ?

Non. Un redémarrage de conteneur (docker restart) relance la même image avec le même binaire PHP vulnérable. Il faut reconstruire l'image à partir d'un tag PHP patché (8.5.12, 8.4.27, 8.3.36 ou 8.2.35), puis recréer le conteneur avec docker compose up -d --force-recreate.

Comment vérifier la version PHP dans un conteneur Docker en cours d'exécution ?

Exécutez docker exec nom-du-conteneur php -v dans un terminal. Le numéro de version affiché doit correspondre à une version patchée : 8.5.12, 8.4.27, 8.3.36 ou 8.2.35. Si la version est inférieure, le conteneur est vulnérable aux CVE-2026-109618 et CVE-2026-109619.

Quelles versions de PHP sont corrigées pour PHP2Shell ?

Les correctifs ont été publiés le 21 octobre 2026 dans les versions PHP 8.5.12, 8.4.27, 8.3.36 et 8.2.35. PHP 8.1 et les versions antérieures sont en fin de vie et ne reçoivent pas de correctif officiel. Les administrateurs doivent migrer vers une branche supportée.

FrankenPHP est-il aussi concerné par PHP2Shell ?

Oui. 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 FrankenPHP avec une version PHP patchée via le script frankenphp-selfbuild.sh.

Faut-il utiliser un tag Docker exact ou un tag flottant pour se protéger ?

Un tag exact (php:8.4.27-fpm) garantit que chaque docker build produit une image contenant le correctif. Un tag flottant (php:8.4-fpm) finira par pointer vers la bonne version, mais sans garantie de délai. Pour les environnements de production, épinglez le tag exact et idéalement le digest SHA256 de l'image.

Qu'est-ce que les Docker Hardened Images pour PHP ?

Les Docker Hardened Images (dhi/php sur le Docker Hub) sont des images PHP renforcées publiées par Docker sous licence Apache 2.0. Elles sont basées sur Debian ou Alpine, ne contiennent ni shell ni gestionnaire de paquets, et s'exécutent en utilisateur non root. Même en cas d'exploitation d'une faille RCE, l'attaquant ne dispose d'aucun outil pour pivoter dans le conteneur.

Comment configurer la mitigation temporaire dans le fichier de configuration PHP ?

Ajoutez session.upload_progress.enabled = 0 dans votre fichier de configuration php.ini ou dans un fichier .ini monté en volume dans le conteneur Docker. Ce réglage désactive le gestionnaire de progression des uploads, vecteur d'attaque de CVE-2026-109619. Les extensions PHP (OPcache, GD, PDO) ne sont pas affectées par cette configuration. Cette mitigation réduit le risque mais ne remplace pas la mise à jour vers une version patchée.

Faut-il sauvegarder les bases de données MySQL ou PostgreSQL avant de reconstruire les conteneurs ?

Oui. Exportez vos bases de données MySQL, MariaDB ou PostgreSQL avec mysqldump ou pg_dump avant toute opération de rebuild. Les volumes Docker ne sont pas supprimés par docker compose down (sans l'option -v), mais un incident de manipulation peut entraîner une perte de données. Sauvegardez aussi les fichiers de configuration personnalisés (docker-compose.yml, .env, configs Nginx ou Apache).

Les conteneurs Docker sous Windows (Docker Desktop) sont-ils vulnérables à PHP2Shell ?

Oui. Docker Desktop sous Windows exécute les conteneurs dans une machine virtuelle Linux via WSL 2 ou Hyper-V. Le runtime PHP embarqué dans l'image Docker est identique à celui des conteneurs Linux. La procédure d'audit et de mise à jour est la même : vérifiez la version PHP avec docker exec, reconstruisez l'image avec un tag patché et recréez le conteneur.

Quels logs vérifier après la mise à jour PHP dans un conteneur Docker ?

Consultez les logs du conteneur PHP avec docker compose logs pour vérifier l'absence d'erreurs au démarrage du daemon PHP-FPM. Vérifiez aussi les logs du serveur web (Nginx ou Apache) pour confirmer que le reverse proxy vers PHP-FPM fonctionne. Recherchez les erreurs 502 Bad Gateway dans les logs Nginx ou les messages de connexion refusée, qui indiqueraient un problème de communication entre le serveur web et le daemon PHP-FPM.

Mon hébergeur gère-t-il la mise à jour PHP dans mes conteneurs Docker ?

Non. Un hébergeur fournit l'infrastructure (VPS, serveur dédié, adresse IP, bande passante, RAM) mais ne gère pas le contenu de vos conteneurs Docker. La mise à jour des images et la reconstruction des conteneurs sont de la responsabilité de l'administrateur du serveur. Chez ElypseCloud, les VPS Linux incluent un accès root complet et Docker préinstallé sur demande pour un contrôle total sur vos conteneurs.

Les extensions PHP (OPcache, GD, PDO, intl) doivent-elles être réinstallées après la mise à jour ?

Si vous utilisez les images officielles php:*-fpm du Docker Hub et que vos extensions sont installées via docker-php-ext-install dans le Dockerfile, elles seront recompilées automatiquement lors du rebuild. Les packages système installés via apt (Debian/Ubuntu) ou apk (Alpine) seront aussi réinstallés. Vérifiez la liste des extensions chargées avec docker compose exec mon-service php -m après le rebuild.