# Failles PHP et PHP2Shell - correctifs et mitigations temporaires

> PHP2Shell : correctifs des failles PHP CVE-2026-109618 et CVE-2026-109619, mesures PHP-FPM, mémoire et filtrage web. Ce que les mitigations couvrent réellement.

- URL canonique : [https://forgetaboutit.fr/blog/failles-php-php2shell-mitigation-cloudlinux-hardenedphp/](https://forgetaboutit.fr/blog/failles-php-php2shell-mitigation-cloudlinux-hardenedphp/)
- Publication : 2026-10-21T11:00:00.000Z
- Dernière mise à jour : 2026-10-21T14:11:00.000Z
- Catégorie : Sécurité
- Sujets : PHP, PHP2Shell, CVE-2026-109618, CVE-2026-109619, Cloudflare, CloudLinux, HardenedPHP, Patch management

**Les failles PHP regroupées sous le nom PHP2Shell, CVE-2026-109618 et CVE-2026-109619, disposent désormais de correctifs.** Les mesures temporaires restent utiles lorsqu'un déploiement ne peut pas être immédiat, mais elles ne couvrent pas toutes les voies d'exploitation.

## Mise à jour du 21 octobre 2026 à 16h11, heure de Paris

Cet article a été publié à 13h, avant la sortie des correctifs. **Les deux avis officiels sont maintenant publics : ils confirment des risques d'exécution de code à distance sans authentification et détaillent les protections partielles.** Cette mise à jour ajoute les versions corrigées et les leviers mémoire, PHP-FPM et PHP 8.5.

| Branche PHP | Première version officielle corrigeant les deux CVE |
| --- | --- |
| 8.2 | **8.2.35** |
| 8.3 | **8.3.36** |
| 8.4 | **8.4.27** |
| 8.5 | **8.5.12** |

**La priorité est d'installer un paquet corrigé et de renouveler les processus PHP en service.** Pour les distributions et les offres de support étendu, contrôlez le bulletin et la révision du paquet : un correctif rétroporté peut conserver un numéro amont plus ancien. [Publication de sécurité PHP du 21 octobre](https://www.php.net/archive/2026.php).

La distinction est essentielle : **réduire une surface d'attaque n'est pas corriger le moteur PHP**. Une mitigation peut être utile immédiatement, à condition de connaître ce qu'elle bloque, ce qu'elle laisse passer et les fonctionnalités qu'elle interrompt.

Notre [premier article sur la fuite d'informations concernant ces failles PHP](/blog/failles-critiques-php-fuite-informations-correctifs/) présente l'alerte initiale. Ici, nous détaillons les leviers de réduction de l'exposition et la piste **CloudLinux HardenedPHP** pour les applications dépendant de branches anciennes.

## PHP2Shell : ce que les avis confirment

**CVE-2026-109618** concerne un état mémoire invalide après une interruption pour manque de mémoire. La RCE est démontrée avec mod_php, avant le code applicatif ; FPM reste susceptible, sans exploit complet démontré pour cette CVE. [Avis sur la corruption OOM](https://github.com/php/php-src/security/advisories/GHSA-w8hw-w9fx-j79w).

**CVE-2026-109619** permet de réutiliser un état d'une requête précédente dans le même worker. Une RCE est validée avec mod_php et FPM, sous conditions applicatives pour ce dernier. Ce n'est donc pas une faille limitée à mod_php ou à PHP 8.5. [Avis sur les états persistants](https://github.com/php/php-src/security/advisories/GHSA-6wmf-4rv5-p3rp).

Les deux avis décrivent une exploitation de complexité élevée, dépendante de l'environnement. **Le risque est confirmé, sans rendre chaque installation exploitable de façon identique.** Bloquer le seul parcours multipart ne suffit pas à couvrir tous les cas.

## 1. Désactiver le suivi de progression des uploads

PHP peut enregistrer dans la session la progression d'un transfert de fichier. La fonction est pilotée par `session.upload_progress.enabled` et n'est pas nécessaire au simple fonctionnement des uploads. [Documentation du suivi de progression PHP](https://www.php.net/manual/en/session.upload-progress.php).

Si vos applications n'en dépendent pas, sa désactivation est une mesure de réduction de surface à examiner. **Elle conserve les uploads et les sessions habituelles**, mais peut supprimer la barre de progression ou le mécanisme d'annulation d'un transfert qui s'appuie sur cette fonction.

Le réglage doit être appliqué au bon endroit, selon la manière dont PHP est exécuté :

| Environnement | Configuration à adapter |
| --- | --- |
| `php.ini` chargé par le PHP web | `session.upload_progress.enabled = Off` |
| Configuration de chaque pool PHP-FPM concerné | `php_admin_flag[session.upload_progress.enabled] = off` |
| Apache avec mod_php, configuration serveur ou VirtualHost | `php_admin_flag session.upload_progress.enabled Off` |
| Nginx ou Apache devant PHP-FPM | Appliquer le réglage dans PHP-FPM, pas une directive mod_php |

Les syntaxes sont documentées pour [les pools PHP-FPM](https://www.php.net/manual/en/install.fpm.configuration.php) et [Apache avec mod_php](https://www.php.net/manual/en/configuration.changes.php). La directive Apache `php_admin_flag` se place dans la configuration serveur ou du VirtualHost, **pas dans un `.htaccess`**.

Validez la configuration, renouvelez tous les workers concernés et vérifiez la valeur réellement utilisée par le PHP web. Un contrôle de PHP CLI ne prouve pas celle du pool qui sert le site. Avec un panneau d'hébergement, utilisez son mécanisme de configuration persistant afin qu'une régénération n'annule pas le changement.

**Un `ini_set()` ajouté au code de l'application n'est pas une réponse adaptée.** PHP documente que les informations de progression sont écrites avant l'exécution des scripts. [Ordre de traitement documenté par PHP](https://www.php.net/manual/en/session.upload-progress.php).

Le bulletin PHP confirme ce levier pour les chemins de session de CVE-2026-109619, mais pas comme protection globale. Sous FPM, un `.user.ini` ne l'applique pas assez tôt pour cet usage. [Consignes officielles PHP](https://www.php.net/archive/2026.php).

## 2. Bloquer le multipart avant son traitement par PHP

`multipart/form-data` est notamment utilisé pour envoyer des fichiers et certains formulaires. Un serveur web ou un proxy peut refuser ce format avant de transmettre la requête à PHP.

Le blocage doit couvrir **toutes les URL servies par le PHP concerné**, pas uniquement une route nommée `/upload`. Un formulaire peut employer ce format même sans fichier sélectionné. En contrepartie, tous les usages légitimes correspondants seront également bloqués : pièces jointes, imports ou envois de documents, par exemple.

Les configurations suivantes sont des exemples à adapter au périmètre retenu. Elles ne sont pas un correctif officiel de PHP2Shell et ne doivent pas être ajoutées sans vérifier les usages du site.

### Avec Nginx

Dans chaque bloc `server` concerné, avant les autres réécritures :

```nginx
if ($http_content_type ~* "multipart/form-data") {
    return 403;
}
```

Le test est insensible à la casse et renvoie une interdiction HTTP. Vérifiez également qu'une directive `error_page 403` ne réinjecte pas la requête dans PHP via une page d'erreur dynamique.

Validez la configuration avant rechargement :

```bash
nginx -t
```

Le rechargement dépend ensuite de votre installation, de son service ou de son conteneur. [Documentation Nginx sur `if` et `return`](https://nginx.org/en/docs/http/ngx_http_rewrite_module.html).

### Avec Apache

Avec `mod_rewrite` activé, dans chaque VirtualHost concerné, avant les autres réécritures :

```apache
RewriteEngine On
RewriteCond %{HTTP:Content-Type} multipart/form-data [NC]
RewriteRule ^ - [F,L]

ErrorDocument 403 default
```

`ErrorDocument 403 default` évite une page d'erreur traitée par PHP. Le bloc peut aussi se placer en tête du `.htaccess` si `AllowOverride FileInfo` l'autorise. [Drapeau Apache `F`](https://httpd.apache.org/docs/2.4/rewrite/flags.html#flag_f), [directive `ErrorDocument`](https://httpd.apache.org/docs/2.4/mod/core.html#errordocument).

Sur une installation Debian ou Ubuntu utilisant cette commande, validez avant rechargement :

```bash
apache2ctl configtest
```

### Pourquoi ne pas simplement désactiver les fichiers dans PHP ?

`file_uploads = Off` ne désactive pas le parseur multipart : le [code de PHP](https://github.com/php/php-src/blob/PHP-8.4/main/rfc1867.c) distingue le traitement des champs du formulaire et celui des parties fichiers. Ce réglage ne doit donc pas être assimilé à un refus de toute requête multipart avant PHP.

`enable_post_data_reading = Off` empêche l'analyse automatique du corps POST : `$_POST` et `$_FILES` ne sont plus remplis. Cela peut casser les formulaires classiques, bien au-delà des seuls uploads. [Documentation PHP de `enable_post_data_reading`](https://www.php.net/manual/en/ini.core.php#ini.enable-post-data-reading).

Dans un pool FPM, la syntaxe correspondante serait :

```text
php_admin_flag[enable_post_data_reading] = off
```

Ce n'est pas la même mesure que désactiver le suivi de progression : **ne les confondez pas**. Pour refuser uniquement le format multipart annoncé par l'en-tête, le filtrage avant PHP est plus ciblé fonctionnellement.

## 3. Cloudflare : filtrer avant l'origine

Pour des hôtes proxifiés par Cloudflare, une **Custom Rule** avec l'action **Block** peut refuser le multipart à l'entrée :

```text
any(lower(http.request.headers["content-type"][*])[*] contains "multipart/form-data")
```

Cette expression examine les valeurs de l'en-tête `Content-Type` sans tenir compte de la casse. Les fonctions et tableaux utilisés sont décrits dans la [documentation du langage de règles Cloudflare](https://developers.cloudflare.com/ruleset-engine/rules-language/values/#arrays).

**Telle quelle, la règle s'applique à tous les hôtes proxifiés de la zone**, toutes les URL et toutes les IP. Définissez le périmètre voulu et placez-la avant les règles `Skip` susceptibles de la contourner. Vérifiez l'ordre effectif des règles et les événements de sécurité. [Fonctionnement des exceptions `Skip`](https://developers.cloudflare.com/waf/custom-rules/skip/).

L'origine doit également être protégée contre les accès directs qui éviteraient Cloudflare. Une requête qui atteint PHP par un autre nom d'hôte ou un autre accès ne passe pas nécessairement par ce filtrage.

### Les exceptions d'upload restent des chemins exposés

Si une interruption complète des uploads est impossible, une exception peut être limitée à **un hôte, un chemin exact et une méthode**. Exemple pédagogique autorisant uniquement `POST /upload` sur `app.example.com` :

```text
any(lower(http.request.headers["content-type"][*])[*] contains "multipart/form-data")
and not (
  http.host eq "app.example.com"
  and http.request.method eq "POST"
  and http.request.uri.path eq "/upload"
)
```

**Cette exception reste risquée : elle ne protège pas le chemin autorisé.** Elle peut réduire les tentatives opportunistes sur les autres URL, mais un attaquant peut viser directement la route exclue. Un contrôle de connexion, de propriété ou d'abonnement effectué dans l'application PHP intervient après le traitement initial du corps de la requête.

Pour les formulaires sans fichier, étudiez un passage à `application/x-www-form-urlencoded` si l'application le permet. Pour les uploads indispensables, privilégiez un PHP corrigé ou un accès restreint par un dispositif placé avant PHP, plutôt qu'une exception large fondée sur un préfixe d'URL.

## 4. Réduire le risque lié aux limites mémoire

Pour CVE-2026-109618, l'avis propose temporairement d'imposer `memory_limit=-1`, sans possibilité de rétablir une limite finie. Un échec d'allocation sous-jacent reste toutefois exploitable. **Ne remplacez pas cette limite par `RLIMIT_AS` ou `RLIMIT_DATA`**, explicitement déconseillés. Une limite cgroup peut encadrer la consommation, sans garantir la protection ; tuer tout le groupe peut arrêter tous les workers. [Limites de cette mitigation](https://github.com/php/php-src/security/advisories/GHSA-w8hw-w9fx-j79w).

Dans un pool FPM, la syntaxe administrative est :

```ini
php_admin_value[memory_limit] = -1
```

**Ce n'est pas un réglage à généraliser sans évaluation de capacité.** La valeur `-1` retire la limite mémoire PHP du script. Il faut anticiper la consommation simultanée des workers et l'impact sur les autres services. [Sens de `memory_limit`](https://www.php.net/manual/en/ini.core.php#ini.memory-limit), [configuration FPM](https://www.php.net/manual/en/install.fpm.configuration.php).

Gardez aussi des limites strictes sur les entrées : taille du corps décodé au frontal, champs, parties multipart, en-têtes, profondeur d'imbrication et uploads. Elles doivent couvrir les requêtes sans `Content-Length` utilisable. Ce sont des protections complémentaires, pas le correctif. [Consignes PHP sur les requêtes et la mémoire](https://www.php.net/archive/2026.php).

## 5. Réduire les chemins d'état persistant

### Limiter la réutilisation des workers FPM

L'avis CVE-2026-109619 suggère, si le coût en performances est acceptable :

```ini
pm.max_requests = 1
```

Le worker est remplacé après chaque requête, ce qui casse l'enchaînement inter-requêtes décrit. **Cela ne corrige pas CVE-2026-109618.** Testez la charge avant généralisation. [Avis officiel](https://github.com/php/php-src/security/advisories/GHSA-6wmf-4rv5-p3rp).

Cette directive appartient à la configuration du pool, pas au `php.ini`. La valeur `0` laisse les workers traiter un nombre illimité de requêtes ; `1` impose leur renouvellement permanent. [Documentation de `pm.max_requests`](https://www.php.net/manual/en/install.fpm.configuration.php).

### Désactiver les backtraces fatales sur PHP 8.5

Sur cette branche uniquement, imposez administrativement :

```ini
fatal_error_backtraces = 0
```

Cela retire le chemin de backtrace confirmé, pas les autres états persistants. Renouvelez tous les workers après application. [Avis CVE-2026-109619](https://github.com/php/php-src/security/advisories/GHSA-6wmf-4rv5-p3rp).

### Corriger les erreurs, pas seulement les masquer

Supprimez les diagnostics de configuration précoces, les erreurs de nettoyage et les erreurs fatales ou timeouts accessibles à un attaquant. Masquer les messages avec `display_errors`, `error_reporting` ou `@` ne protège pas ; des journaux silencieux ne prouvent pas la sécurité. [Recommandations et audit](https://github.com/php/php-src/security/advisories/GHSA-6wmf-4rv5-p3rp).

## 6. CloudLinux HardenedPHP : une piste pour les branches anciennes

Une application peut dépendre d'une branche PHP que le projet ne maintient plus. **HardenedPHP, proposé par CloudLinux, rétroporte des correctifs de sécurité sur certaines versions historiques**. C'est une piste de maintenance étendue à examiner lorsqu'une migration applicative ne peut pas être réalisée immédiatement. [Présentation de HardenedPHP par CloudLinux](https://cloudlinux.com/solutions/for-hosting-providers/).

Il faut distinguer cette maintenance du filtrage WAF. HardenedPHP vise le moteur et ses paquets ; un WAF tente de bloquer des requêtes avant qu'elles l'atteignent. Une signature d'attaque bloquée ne signifie pas que le paquet PHP est corrigé.

Dans la mise à jour de son [bulletin consacré précisément à CVE-2026-109618 et CVE-2026-109619](https://cloudlinux.statuspage.io/incidents/zl0vt1yq3dj5), publiée le 21 octobre à 11h26 heure de Paris, CloudLinux indique :

- une règle de blocage et une règle de télémétrie livrées dans le jeu de règles **Imunify360 8.83**, canal Stable ; leur distribution est automatique sur les serveurs utilisant Imunify360 avec le WAF ModSecurity activé ;
- des tentatives correspondant au motif filtré déjà observées, ce qui ne prouve pas à lui seul une compromission réussie ;
- la préparation de **paquets alt-php corrigés**, sans calendrier détaillé encore fourni dans cette mise à jour.

CloudLinux présente bien ces premières protections comme **temporaires et incomplètes**. Ni la désactivation de la progression ni la présence du WAF ne remplacent l'installation des correctifs.

Ce bulletin décrit l'état de préparation des paquets à cette heure-là, pas une disponibilité actuelle garantie pour chaque branche. PHP a depuis publié ses correctifs officiels : vérifiez séparément ceux de votre fournisseur. **HardenedPHP est une voie de maintenance du moteur, pas une alternative au fait de le corriger.**

Pour retenir la piste HardenedPHP, faites confirmer **la branche, la plateforme, le paquet et la révision qui corrigent ces deux CVE**, ainsi que le PHP réellement utilisé par le site. La présence d'une ancienne version dans un sélecteur ne démontre pas son niveau de maintenance. Les possibilités dépendent aussi du système, du panneau d'hébergement et de l'offre souscrite. [Documentation des paquets alt-php](https://docs.cloudlinux.com/cloudlinuxos/cloudlinux_os_components/).

Ce support peut permettre de gagner du temps pour organiser une migration. Il ne met pas à jour les extensions, le CMS ou le code métier à la place de leurs mainteneurs.

## Vérifier le filtrage et le déploiement du correctif

Avant toute modification, conservez la configuration initiale et identifiez les fonctionnalités qui seront touchées. Appliquez les exemples uniquement sur les environnements que vous êtes autorisé à administrer.

La vérification doit répondre à plusieurs questions :

1. Le suivi de progression est-il bien désactivé dans **chaque pool ou version PHP web** du périmètre ?
2. Une requête multipart de test est-elle refusée **avant PHP**, y compris sur une URL sans fonction d'upload ?
3. La réponse 403 vient-elle du filtre prévu, sans page d'erreur PHP ni accès direct contournant la protection ?
4. Les formulaires classiques fonctionnent-ils encore et les uploads indispensables ont-ils un traitement prévu ?
5. Les exceptions et les journaux sont-ils suivis, avec une personne chargée de vérifier la disponibilité du paquet fournisseur et de le déployer ?
6. Les réglages temporaires ajoutés au pool sont-ils persistants, effectivement chargés et compatibles avec la capacité du service ?

**Un test de filtrage n'est pas un test d'absence de vulnérabilité.** Il ne faut ni exécuter un exploit sur un service métier pour « vérifier », ni considérer un 403 comme la preuve que PHP a été corrigé.

Les avis officiels étant publiés, rapprochez-les de l'inventaire et des bulletins de votre fournisseur. Mettez à jour les moteurs concernés, renouvelez les processus selon les instructions applicables, puis contrôlez les services. Avec Docker, cela inclut les images qui embarquent PHP et leur redéploiement, pas seulement l'hôte.

La levée des restrictions temporaires doit elle aussi être décidée et vérifiée : retrouver les fonctionnalités attendues, sans retirer une protection en oubliant une ancienne instance ou un autre pool PHP.

## Notre lecture opérationnelle

Face à ces failles PHP, le bon arbitrage n'est pas « ne rien faire » ou « bloquer tous les sites sans distinction ». Il consiste à **choisir une réduction d'exposition explicite, mesurer son impact et conserver la mise à jour comme objectif**.

L'intérêt d'une [infogérance de serveurs Linux](/infogerance/) est de relier ces décisions au fonctionnement réel des applications : versions multiples, conteneurs, reverse proxies, hébergeurs et maintenance des branches anciennes. Le [suivi des CVE](/blog/suivi-cve-pourquoi-quotidien/) doit aboutir à une action vérifiable, pas seulement à une alerte supplémentaire.

Vous avez besoin de cadrer une mitigation temporaire ou de vérifier le support de vos versions PHP ? [Faisons le point sur votre infrastructure](/contact/).

## Questions fréquentes

### Existe-t-il une mitigation officiellement validée par PHP pour PHP2Shell ?

PHP documente désormais des mesures temporaires ciblées, mais aucun contournement de configuration complet pour les deux CVE. Seule l'installation d'une version ou d'un paquet contenant les correctifs apporte une correction complète.

### Désactiver le suivi de progression empêche-t-il les uploads ?

Non. Ce réglage désactive le suivi de progression des uploads enregistré dans les sessions PHP, pas les uploads ni les sessions habituelles. Les applications qui utilisent ce suivi peuvent perdre leur indication de progression.

### Un blocage multipart avec une réponse 403 prouve-t-il que PHP est corrigé ?

Non. Il montre seulement que la requête testée a été bloquée à cet endroit. Le moteur PHP n'est pas corrigé pour autant, et les exceptions, accès directs ou autres chemins doivent être examinés.

### CloudLinux HardenedPHP peut-il aider pour un ancien PHP ?

Oui, c'est une piste de maintenance étendue pour certaines branches anciennes. Il faut confirmer la prise en charge de la version utilisée, la disponibilité du paquet corrigeant ces CVE et son déploiement effectif. Une annonce de préparation ne suffit pas.

## Sources

- [PHP - publication de sécurité du 21 octobre 2026, versions corrigées et mesures temporaires](https://www.php.net/archive/2026.php).
- [PHP - CVE-2026-109618 : RCE via corruption après épuisement mémoire](https://github.com/php/php-src/security/advisories/GHSA-w8hw-w9fx-j79w).
- [PHP - CVE-2026-109619 : RCE via états persistants entre requêtes](https://github.com/php/php-src/security/advisories/GHSA-6wmf-4rv5-p3rp).
- [CloudLinux - bulletin sur les deux CVE, premières mitigations et préparation des paquets alt-php](https://cloudlinux.statuspage.io/incidents/zl0vt1yq3dj5).
- [CloudLinux - maintenance des versions anciennes avec HardenedPHP](https://cloudlinux.com/solutions/for-hosting-providers/).
- [CloudLinux - documentation des composants et paquets alt-php](https://docs.cloudlinux.com/cloudlinuxos/cloudlinux_os_components/).
- [PHP - suivi de progression des uploads en session](https://www.php.net/manual/en/session.upload-progress.php).
- [PHP - configuration des pools FPM](https://www.php.net/manual/en/install.fpm.configuration.php).
- [PHP - configuration avec Apache/mod_php](https://www.php.net/manual/en/configuration.changes.php).
- [PHP - fonctionnement de la limite mémoire](https://www.php.net/manual/en/ini.core.php#ini.memory-limit).
- [PHP - lecture automatique des données POST](https://www.php.net/manual/en/ini.core.php#ini.enable-post-data-reading).
- [PHP - implémentation du traitement multipart](https://github.com/php/php-src/blob/PHP-8.4/main/rfc1867.c).
- [Nginx - traitement des réécritures et réponses conditionnelles](https://nginx.org/en/docs/http/ngx_http_rewrite_module.html).
- [Apache - refus avec le drapeau F](https://httpd.apache.org/docs/2.4/rewrite/flags.html#flag_f) et [gestion des pages d'erreur](https://httpd.apache.org/docs/2.4/mod/core.html#errordocument).
- [Cloudflare - expressions et tableaux](https://developers.cloudflare.com/ruleset-engine/rules-language/values/#arrays) et [gestion des règles Skip](https://developers.cloudflare.com/waf/custom-rules/skip/).
