Le 20 octobre 2026, deux failles graves ont été rendues publiques dans le cœur de PHP. Le nom courant est PHP2Shell et les identifiants sont CVE-2026-109618 et CVE-2026-109619. Le score CVSS est de 9,2. Elles permettent d’exécuter du code sur le serveur sans s’authentifier, et des attaques ont déjà été observées.

Dans cet article, j’explique ce que c’est et quelles versions de PHP sont concernées. Je raconte comment j’ai sécurisé les serveurs que je gère pendant que le correctif n’existait pas, et comment je suis arrivé à la mise à jour définitive. Tu trouveras aussi le script que j’ai utilisé et les commandes pour le lancer.
Qu’est-ce que PHP2Shell
Le problème vient de la façon dont PHP lit les requêtes de type multipart/form-data. C’est le format que le navigateur utilise pour envoyer des fichiers. PHP l’interprète avant le démarrage de n’importe quel script.
Il n’y a donc pas besoin d’un module d’upload. Une seule requête vers un fichier PHP quelconque du site peut suffire.
Les deux failles, en bref :
- CVE-2026-109618. Si la mémoire s’épuise pendant que PHP lit la requête, certaines données se corrompent. La corruption apparaît lors du nettoyage final de la requête et peut mener à l’exécution de code.
- CVE-2026-109619. Une partie de l’état d’une requête reste en mémoire. Une requête suivante, sur le même processus, la réutilise.
Ces détails techniques viennent de l’analyse du NCSC néerlandais et d’autres sources publiques. Je n’ai pas essayé d’exploiter les failles sur mes serveurs.
Quelles versions de PHP sont concernées
Les versions corrigées sont sorties le 21 octobre 2026 : PHP 8.5.12, 8.4.27, 8.3.36 et 8.2.35. Toute version antérieure est touchée.
Les branches 8.1 et plus anciennes n’ont pas de version corrigée officielle, parce qu’elles ne sont plus supportées. PHP a publié seulement des backports minimaux du code source pour 7.4, 8.0 et 8.1. Pour les branches encore plus anciennes, rien n’est indiqué.
Le risque concerne toutes les façons d’exécuter PHP. La plus exposée est mod_php. PHP-FPM, php-cgi, FrankenPHP et LiteSpeed comptent aussi. Cela touche ensuite chaque application qui tourne dessus : WordPress, Joomla, Drupal, Nextcloud, phpMyAdmin, Roundcube et le panneau ISPConfig.
Sur Debian, il y a un détail à connaître. Debian applique les corrections sous forme de backports et ne change pas le numéro de version de PHP. Un serveur peut afficher un numéro bas et être déjà corrigé. C’est pourquoi le script ne compare pas les versions. Il vérifie si le changelog du paquet installé cite les deux CVE.
L’atténuation, en attendant le patch
Quand les failles sont devenues publiques, les correctifs n’étaient pas encore disponibles pour les distributions. Je ne voulais pas laisser les serveurs à découvert, alors j’ai réduit le risque avec un script.
L’atténuation n’est pas un patch. Désactiver session.upload_progress ne ferme qu’un des chemins connus de la CVE-2026-109619 et ne fait rien contre la CVE-2026-109618. Elle servait à réduire la marge d’attaque jusqu’à la mise à jour, pas à la remplacer.
Ce que fait le script
Le script est prévu pour Debian 12 et 13. Il fonctionne avec Apache (mod_php, FastCGI, suPHP, PHP-FPM) et avec Nginx (PHP-FPM). Il reconnaît les serveurs gérés avec ISPConfig, aussi bien Apache que Nginx.
Les options :
- Sans option, il contrôle, c’est tout. Pour chaque paquet PHP, il vérifie que le changelog cite les deux CVE. Il signale les processus qui utilisent encore un ancien binaire, lit les réglages actifs et les ports web en écoute.
--updatemet d’abord à jour l’index des paquets.--logscherche des indices suspects : fichiers PHP récents dans les dossiers d’upload ou de cache, motifs typiques des webshells, références à php2shell dans les logs. C’est une heuristique, elle ne prouve pas une compromission.--hardenapplique la sécurisation décrite plus bas.--dry-run, avec--harden, montre ce qu’il ferait sans rien modifier.--skip-disable-functions, avec--harden, ne touche pas àdisable_functions.--rollbackretire ce qu’a appliqué--harden.
Ce que change –harden
Pour chaque version de PHP présente dans /etc/php, le script crée le fichier mods-available/cve-hardening.ini. Il l’active avec phpenmod pour les SAPI fpm, apache2 et cgi. La protection vaut ainsi pour tous les sites d’un coup.
Les php.ini d’origine restent intacts. La CLI n’est pas touchée, donc composer, artisan et wp-cli continuent de fonctionner.
Le fichier règle trois choses :
session.upload_progress.enabled = Offexpose_php = Offdisable_functionsavec exec, passthru, shell_exec, system, proc_open, popen et pcntl_exec, ajoutées à celles déjà présentes.
Ensuite le script teste la configuration et recharge PHP-FPM et Apache seulement si le test passe. Avant d’écrire, il fait une sauvegarde dans /var/backups/php-cve-hardening/.
Les limites à connaître
disable_functionspeut casser certaines applications, par exemple WordPress avec certains plugins ou Magento. Si ça arrive, utilise--rollbackou relance avec--skip-disable-functions.- Les directives
php_admin_valuedans les pools PHP-FPM ont la priorité sur le fichier global. Le script les signale mais ne les modifie pas. - Avec ISPConfig, les fichiers de
pool.dsont régénérés par le panneau. Les surcharges se corrigent depuis le panneau, dans Sites, Website, Options, Custom php.ini settings, pas à la main. - Les
php.inipropres à chaque site (mode FastCGI ou suPHP d’ISPConfig) et les versions de PHP dans/optne sont pas gérés. Il faut les contrôler à part.
Comment lancer le script
Le script est ici : https://cisilino.com/mscripts/php20261.sh
Avant d’exécuter quoi que ce soit venu d’internet, lis-le. Tu peux le télécharger et l’ouvrir :
wget -qO php20261.sh https://cisilino.com/mscripts/php20261.sh
less php20261.sh
Si tu veux le lancer directement à distance, il faut les droits root. Voici les commandes, dans l’ordre que je conseille.
1. Contrôle seul, avec mise à jour de l’index des paquets :
wget -qO- https://cisilino.com/mscripts/php20261.sh | sudo bash -s -- --update
2. Simulation de la sécurisation, sans modification :
wget -qO- https://cisilino.com/mscripts/php20261.sh | sudo bash -s -- --harden --dry-run
3. Application :
wget -qO- https://cisilino.com/mscripts/php20261.sh | sudo bash -s -- --harden
4. Retrait, si quelque chose casse :
wget -qO- https://cisilino.com/mscripts/php20261.sh | sudo bash -s -- --rollback
Après --harden et après --rollback, pas besoin de redémarrer quoi que ce soit à la main : le script recharge lui-même PHP-FPM et Apache, après avoir testé la configuration. Le redémarrage est en revanche nécessaire après la mise à jour du paquet PHP, car les processus en cours gardent l’ancien binaire en mémoire :
sudo systemctl restart 'php*-fpm' apache2
Les apostrophes autour de php*-fpm sont nécessaires. Sans elles, c’est le shell qui développe l’astérisque, pas systemctl. Si le serveur utilise seulement Nginx, retire apache2.
Le résultat du script est aussi un code de sortie : 0 si tout va bien, 1 s’il y a des avertissements, 2 si le système est vulnérable ou si une action est nécessaire.
Sur les serveurs avec ISPConfig : ispconfig-multipart-guard
Qui utilise ISPConfig a une arme de plus. Le projet a publié le script ispconfig-multipart-guard, décrit dans l’avis officiel d’ISPConfig.
Le principe est simple. Si le problème est dans les requêtes multipart, le serveur web les arrête avant qu’elles n’arrivent à PHP :
- il bloque les requêtes
Content-Type: multipart/...pour tous les sites, pour certains sites choisis ou pour le panneau de contrôle ; - avec Nginx, il répond 415 aux requêtes PHP des sites bloqués et les fichiers statiques ne changent pas. Avec Apache, il répond 403, même pour les fichiers statiques ;
- par défaut, il bloque seulement le panneau ISPConfig. Les sites se bloquent avec des commandes comme
block alloublock esempio.it; - il crée un cron qui, toutes les 5 minutes, rétablit ses hooks si ISPConfig réécrit la configuration ;
- il a une liste d’IP autorisées qui peuvent encore envoyer des fichiers.
Il fonctionne avec Debian et Ubuntu, avec ISPConfig 3.2 ou 3.3 (et même sans ISPConfig), avec Nginx ou avec Apache 2.4 et suivants.
Le prix à payer : sur les sites bloqués, les uploads ne fonctionnent pas. Cela vaut aussi pour les médias des CMS, les pièces jointes des formulaires et celles du webmail, et les imports de phpMyAdmin. Les pages normales et les formulaires urlencoded continuent de fonctionner. Là aussi, c’est une mesure provisoire et non une correction.
Ce script et le mien ne sont pas des alternatives. Le mien agit sur la configuration de PHP, celui d’ISPConfig sur le serveur web. Je ne les ai pas comparés sur le terrain et je ne peux pas te dire comment ils se comportent ensemble sur chaque configuration.
La mise à jour définitive, en deux étapes
Les atténuations devaient durer peu. J’ai mis à jour les serveurs dès que les mises à jour ont été disponibles, en deux étapes :
- Compilation directe. En attendant que la distribution utilisée sur chaque serveur publie son paquet, j’ai compilé PHP depuis les sources dans les versions corrigées.
- Paquet officiel. Quand le paquet officiel de la distribution est sorti pour ce serveur, j’ai remplacé la compilation par le paquet.
La deuxième étape compte. Un PHP compilé à la main ne se met pas à jour tout seul avec le reste du système. Le paquet de la distribution, si, et le script peut le vérifier en lisant le changelog.
Que faire maintenant
- Mets PHP à jour vers la 8.5.12, 8.4.27, 8.3.36 ou 8.2.35. Sur Debian, tu peux aussi utiliser le paquet de la distribution quand le changelog cite les deux CVE.
- Redémarre PHP-FPM et Apache, puis relance le script sans option. Il ne doit plus signaler de problème.
- Si tu utilises PHP 8.1 ou antérieur, prévois le passage à une branche supportée. Pour ces branches, il n’y a pas de version officielle corrigée.
- Garde
session.upload_progressdésactivé jusqu’à la prochaine publication de correctifs, si ton application ne l’utilise pas. - Contrôle les logs et les fichiers récents, avec
--logsou à la main, en cherchant des fichiers PHP apparus dans les dossiers d’upload. - N’oublie pas PHP dans les conteneurs, les images et les appliances de tiers. Ils se mettent à jour à part.
- Si ton site utilise WordPress, le plugin Cisilino Site Defense Network ne résout pas PHP2Shell. Il protège toutefois la connexion et tient un journal des activités, utile pour comprendre ce qui se passe sur le site.
Sources
- ISPConfig : PHP2Shell, vulnérabilités critiques de PHP (CVE-2026-109618, CVE-2026-109619)
- NCSC-NL : wiki sur PHP2Shell
ISPConfig, PHP, Debian et les autres noms cités sont des marques de leurs propriétaires respectifs. Ils sont indiqués uniquement pour identifier les produits.

Laisser un commentaire