PHP2Shell : comment sécuriser votre serveur

Vous souhaitez mettre à jour votre serveur Linux ? Cliquez sur l’article de blog ci-dessous :

« Si vous faites tourner des sites web ou des applications sous PHP, effectuez la mise à jour dès aujourd’hui. Le mercredi 21 octobre 2026 à 16h00, heure néerlandaise (14h00 UTC), l’équipe PHP publiera une mise à jour d’urgence pour deux failles critiques connues sous le nom de PHP2Shell. Les détails étaient déjà dans la nature avant que le correctif ne soit prêt, les attaquants ont donc une longueur d’avance.

Dans cet article, vous découvrirez ce qu’est PHP2Shell, comment protéger temporairement votre serveur en attendant le correctif, comment effectuer la mise à jour en toute sécurité par la suite et comment vérifier si quelqu’un s’est déjà introduit dans votre système.

Cet article a été mis à jour jusqu’au mercredi matin 21 octobre. Dès que PHP publiera la liste officielle des versions affectées et corrigées, nous le mettrons à jour.

Qu’est-ce que PHP2Shell ?

PHP2Shell est le surnom de deux vulnérabilités dans PHP lui-même : CVE-2026-109618 et CVE-2026-109619. L’équipe PHP attribue à chacune un score de 9,2 sur 10 (CVSS v4.0). Selon le CERT-EU, entre autres, un attaquant peut exécuter son propre code sur votre serveur sans authentification (exécution de code à distance).

Le nom provient d’un outil d’exploitation apparu dans une capture d’écran divulguée. Le mardi après-midi 20 octobre, les premiers détails sont apparus en ligne, bien avant l’annonce prévue. La société de sécurité Sansec prévoit des attaques massives dans les quinze minutes suivant la sortie du correctif, car les attaquants pourront alors voir exactement ce qui a été réparé.

Où se situe la faille ?

PHP n’a pas encore confirmé la cause technique. Des chercheurs indépendants pointent du doigt la manière dont PHP traite les requêtes multipart : le format utilisé par un navigateur pour envoyer des formulaires avec des fichiers. Selon eux, il s’agirait d’une erreur de mémoire (use-after-free) dans la fonction session upload progress, qui suit l’état d’avancement d’un téléchargement. Cette fonction est activée par défaut.

Le plus important à retenir : la faille se trouve dans PHP lui-même, pas dans WordPress, Laravel ou une extension. PHP traite la requête avant même que votre application n’exécute la moindre ligne de code. Un site sans formulaire de téléchargement n’est donc pas automatiquement en sécurité, et la mise à jour de WordPress ne résoudra pas ce problème.

Êtes-vous vulnérable ?

Partez du principe que oui si vous utilisez PHP. La liste officielle des versions concernées ne suivra qu’avec la version corrigée, mais les signaux sont clairs :

Version PHPStatutQue faire
8.2, 8.3, 8.4, 8.5Prise en charge, recevra un correctifMesures temporaires aujourd’hui, mise à jour après 16h00
8.1 et antérieuresFin de vie, ne recevra probablement aucun correctifMaintenir les mesures temporaires et mettre à niveau dès que possible
InconnuInventorierIdentifier d’abord quelle version de PHP dessert réellement votre site (étape 1)

watchTowr et le CERT-EU considèrent que les versions à partir de PHP 5 sont touchées. Si vous tournez encore sous Ubuntu 20.04 avec PHP provenant du PPA d’Ondřej Surý, il n’y aura probablement pas de paquet mis à jour pour vous : ce PPA ne fournit plus de mises à jour que pour Ubuntu 22.04 et 24.04.

Étape 1 : répertoriez tout votre environnement PHP

Vous ne pouvez corriger que ce que vous connaissez. Dressez une liste de chaque serveur et de chaque site utilisant PHP, y compris les environnements de pré-production, les anciens sites de campagne, les outils d’administration comme phpMyAdmin et les conteneurs. Notez pour chaque hôte les versions de PHP présentes, la provenance de PHP (paquets de distribution, PPA, image Docker, panneau d’hébergement) et si l’hôte est accessible depuis Internet.

Sur un serveur Debian ou Ubuntu, vous pouvez commencer par :

# Welke PHP-versies zijn geïnstalleerd?
ls /etc/php

# Welke PHP-processen draaien er?
ps -eo pid,comm,args | grep -E '[p]hp-fpm|[a]pache2|[h]ttpd|[l]sphp'

# Welke sites geven verzoeken door aan PHP?
sudo nginx -T | grep -E 'server_name|fastcgi_pass'

# Luistert PHP ergens rechtstreeks op een poort?
sudo ss -tlnp

Attention : php -v sur la ligne de commande ne dit rien sur la version qui dessert votre site web. PHP-FPM, le module Apache mod_php et les pools FPM séparés peuvent chacun charger une version différente et un fichier php.ini différent. Ne mettez jamais non plus une page phpinfo() publique en ligne pour vérifier cela.

Étape 2 : mesures temporaires jusqu’au correctif

La seule véritable solution est de mettre à jour PHP. Un développeur principal de PHP l’a dit littéralement : le correctif est la seule atténuation possible. Les deux mesures ci-dessous ne sont pas officielles de PHP, mais elles réduisent considérablement le risque pour les heures précédant la mise à jour. Appliquez les deux.

A. Désactivez session upload progress

Dans le php.ini de votre serveur web (pas seulement celui du CLI) :

session.upload_progress.enabled = Off

Si vous utilisez PHP-FPM, fixez également ce paramètre dans chaque pool, afin qu’un .user.ini dans un répertoire web ne puisse pas le réactiver discrètement. Sur Debian/Ubuntu, les pools se trouvent dans /etc/php/<versie>/fpm/pool.d/ :

php_admin_flag[session.upload_progress.enabled] = off

Redémarrez ensuite PHP-FPM pour chaque version, par exemple sudo systemctl restart php8.3-fpm. La seule chose que vous remarquerez : les barres de progression s’appuyant sur cette fonction PHP ne fonctionneront plus.

Hébergement mutualisé ? Placez la ligne ci-dessus dans un fichier .user.ini à côté de votre index.php (pour PHP-FPM ; cela peut prendre jusqu’à 5 minutes avant d’être actif). Si PHP fonctionne comme module Apache, utilisez dans .htaccess : php_flag session.upload_progress.enabled off. Si vous obtenez ensuite une erreur 500, retirez la ligne et demandez de l’aide à votre hébergeur.

B. Bloquez les requêtes multipart sur le serveur web

C’est la mesure temporaire la plus efficace : refusez toute requête contenant « multipart » dans l’en-tête Content-Type, avant qu’elle n’atteigne PHP. Faites-le pour toutes les méthodes HTTP (PHP 8.4 peut également traiter le multipart avec PUT et PATCH) et dans chaque bloc serveur ou hôte virtuel qui transmet à PHP, y compris le bloc par défaut (catch-all). Les attaquants envoient également des requêtes directement vers votre adresse IP.

Nginx — dans le contexte http, par exemple dans /etc/nginx/conf.d/block-multipart.conf :

map $http_content_type $block_multipart {
    default       0;
    "~*multipart" 1;
}

Et en haut de chaque bloc serveur qui transmet à PHP :

if ($block_multipart) {
    return 403;
}

Vérifiez avec sudo nginx -t et rechargez nginx.

Apache 2.4 — dans l’hôte virtuel ou en haut du fichier .htaccess (au-dessus des règles WordPress) :

<If "req('Content-Type') =~ /multipart/i">
    Require all denied
</If>

Utilisez bien ici req('Content-Type') et non %{CONTENT_TYPE} : ce dernier examine la réponse au lieu de la requête, ce qui rend le blocage inefficace.

LiteSpeed — en haut du fichier .htaccess, en dehors du bloc WordPress, puis redémarrez LiteSpeed :

RewriteEngine On
RewriteCond %{HTTP:Content-Type} multipart [NC]
RewriteRule ^ - [F]

Cloudflare (complément, pas un remplacement) — une règle personnalisée (Custom Rule) avec l’action Block et l’expression :

any(lower(http.request.headers["content-type"][*])[*] contains "multipart")

Cloudflare ne protège que le trafic qui passe par Cloudflare. Appliquez donc également le blocage sur le serveur lui-même, ou n’autorisez les ports 80 et 443 qu’à recevoir du trafic provenant des plages IP de Cloudflare.

Tests — depuis une autre machine, aussi bien via votre domaine que directement vers l’IP de votre serveur :

curl -sS -o /dev/null -w '%{http_code}\n' -F test=1 https://jouwdomein.nl/
curl -sS -o /dev/null -w '%{http_code}\n' -X PUT -F test=1 https://jouwdomein.nl/index.php
curl -sS -o /dev/null -w '%{http_code}\n' -F test=1 --resolve jouwdomein.nl:443:<server-ip> https://jouwdomein.nl/

Vous voulez voir un code 403 partout. Attention : une extension de sécurité WordPress peut également renvoyer un 403, mais elle ne s’exécute qu’après que PHP a déjà traité la requête. Vérifiez donc que la page 403 provient bien de votre serveur web.

Effets secondaires : tant que le blocage est en place, les téléchargements de fichiers ne fonctionneront pas. Pensez à la bibliothèque de médias WordPress, aux formulaires avec pièces jointes, aux téléchargements Livewire et Filament. Contact Form 7 envoie également les formulaires classiques en multipart, testez donc vos formulaires les plus importants. Les pages normales, la connexion et les API JSON continueront de fonctionner normalement.

C. Réduisez votre surface d’attaque

  • Mettez hors ligne les sites de pré-production et les applications PHP dont vous n’avez pas besoin aujourd’hui jusqu’à ce qu’ils soient corrigés.
  • Limitez l’accès aux outils d’administration comme phpMyAdmin à votre propre adresse IP (allow + deny all; dans nginx).
  • Assurez-vous que votre serveur n’est pas accessible en dehors de votre CDN ou WAF.

Ce qui n’aide PAS

Tout ce qui ne s’exécute qu’après que PHP a lu la requête arrive trop tard. Ne comptez donc pas sur :

  • La mise à jour de WordPress ou des extensions. La faille est dans PHP, pas dans votre CMS.
  • Les extensions de sécurité comme Wordfence. Même le pare-feu de Wordfence (via auto_prepend_file) ne s’exécute qu’une fois que PHP a déjà traité la requête multipart.
  • file_uploads = Off. PHP lit toujours la requête multipart ; il ignore simplement les fichiers.
  • disable_functions. Le blocage de fonctions comme system() ne corrige pas l’erreur de traitement.
  • Une petite valeur post_max_size. Aucune limite sûre n’est connue.
  • Uniquement un WAF ou un CDN. Cela n’aide que si votre serveur n’est pas accessible directement via son adresse IP.
  • Le mode maintenance de Laravel ou un message 419. Ceux-ci n’apparaissent qu’après que PHP a déjà traité la requête.

Étape 3 : mise à jour dès que le correctif est disponible

À partir de 16h00, surveillez php.net, la liste de diffusion php.announce et les avis de sécurité de votre distribution. PHP peut également publier le correctif plus tôt si des attaques actives sont constatées. Mettez d’abord à jour vos serveurs exposés sur Internet, puis les autres.

Avant de commencer, conservez une copie des journaux (logs) de votre serveur web et de PHP à partir du 20 octobre. Vous en aurez besoin à l’étape 4, et un déploiement ou une rotation des logs pourrait les effacer.

Debian et Ubuntu

sudo apt update

# Staat er een pakket op 'hold'? Dan doet de update stilletjes niets.
apt-mark showhold

# Welke versie staat er en welke is beschikbaar?
apt-cache policy php8.3-fpm

sudo apt upgrade

Mettez à jour chaque version de PHP installée, pas seulement la version vers laquelle pointe la commande php. Les distributions comme Debian et Ubuntu appliquent souvent les correctifs de sécurité sur la version existante (backport). Le numéro de version peut alors sembler ancien alors que le correctif est bien présent. Vérifiez cela dans le journal des modifications (changelog) :

zcat /usr/share/doc/php8.3-fpm/changelog.Debian.gz | head -20

Si vous avez beaucoup de retard sur les mises à jour, gardez à l’esprit que vous importerez également d’autres changements. Vérifiez ensuite rapidement le fonctionnement de votre site.

Redémarrer, et cette fois-ci vraiment tout

  • Redémarrez PHP-FPM pour chaque version, ou Apache si PHP fonctionne en tant que module.
  • Redémarrez les processus PHP à exécution longue : queue workers, Laravel Horizon, schedulers, Reverb, Octane. Sinon, ils continueront d’utiliser l’ancien PHP.
  • Recherchez les processus qui tournent encore sur l’ancien binaire PHP remplacé :
ls -l /proc/*/exe 2>/dev/null | grep -i 'php.*deleted'

Docker, hébergement et panneaux de contrôle

  • Docker : un hôte mis à jour ne répare pas le PHP dans vos conteneurs. Récupérez l’image de base corrigée, reconstruisez et déployez. Vérifiez avec docker run --rm jouw-image php -v.
  • FrankenPHP : PHP est intégré au binaire lui-même, vous avez donc besoin d’une nouvelle version de FrankenPHP.
  • Hébergement mutualisé ou infogéré, cPanel, Plesk, DirectAdmin : demandez à votre hébergeur de confirmer quelle version corrigée de PHP dessert votre domaine. Passer à une autre version de PHP dans le panneau ne garantit pas que cette version est corrigée.
  • PHP 8.1 ou antérieur : maintenez les mesures temporaires ou gardez le site hors ligne jusqu’à ce que vous ayez effectué la mise à niveau.

Étape 4 : vérifiez si quelqu’un s’est déjà introduit

Le correctif ferme la porte, mais ne dit rien sur ceux qui l’ont déjà franchie. Remontez jusqu’au mardi 20 octobre vers 17h00, heure néerlandaise, peu avant les premiers messages publics sur la faille.

  • Recherchez dans vos journaux de serveur web et de PHP des requêtes multipart inhabituelles et des plantages de workers PHP-FPM.
  • Recherchez des fichiers nouveaux ou modifiés dans les racines web, les dossiers de téléchargement, les extensions et les mu-plugins : find /var/www -type f -newermt '2026-10-20 15:00 UTC' (attendez-vous à du bruit provenant des caches et des logs).
  • Vérifiez les modifications des fichiers .user.ini et du paramètre auto_prepend_file.
  • Passez en revue les tâches cron, les unités systemd et Supervisor pour de nouvelles tâches, et vérifiez les nouvelles clés SSH.
  • Surveillez les processus PHP qui lancent un shell, Python ou curl/wget, ainsi que les connexions sortantes inattendues de l’utilisateur PHP.
  • Vérifiez dans vos applications si de nouveaux comptes administrateurs ont été créés.

Vous trouvez quelque chose ? Isolez le serveur et conservez les journaux. Si les preuves indiquent une intrusion, reconstruisez le serveur et modifiez chaque secret auquel l’utilisateur PHP avait accès : fichiers .env, mots de passe de base de données, clés API et clés d’application. Un contrôle vierge n’est pas une garantie, mais c’est un bon signe.

Après le correctif : nettoyage des mesures temporaires

La version corrigée de PHP tourne-t-elle de manière prouvée sur votre site ? Supprimez alors le blocage multipart de votre serveur web et de Cloudflare. Testez ensuite un téléchargement de fichier et les formulaires qui ne fonctionnaient temporairement plus. Session upload progress peut rester désactivé, à moins que votre application n’utilise cette fonction.

Besoin d’aide ?

Les clients bénéficiant de la gestion de serveur n’ont rien à faire : nous avons déjà mis en place les mesures temporaires et nous appliquerons le correctif dès que la mise à jour sera disponible.

Vous n’avez pas de contrat de maintenance ou vous n’êtes pas sûr que votre serveur soit bien protégé ? Contactez Servermeister via [email protected] ou au 020 895 0045. Nous examinerons votre situation dès aujourd’hui.

Block "serverbeheer-aanbod-content" not found

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *