# Sécuriser Nginx avec PHP-FPM

> Sécurité Nginx PHP-FPM après PHP2Shell : vérifier pools et versions, redémarrer tous les workers, définir les valeurs transitoires avec php_admin_value.

Source : https://phpsos.de/fr/server/nginx-php-fpm/  
État : 25/10/2026  
Fournisseur : PHP SOS, Assistance d'urgence PHP et sécurité des serveurs. Aide immédiate par WhatsApp : https://wa.me/491736494914?text=Bonjour%20PHP%20SOS%2C%20nous%20avons%20besoin%20d%27aide%20avec%20notre%20serveur%20PHP.%20Entreprise%20%3A%20%E2%80%A6%20Site%20web%20%3A%20%E2%80%A6

**En bref :** avec Nginx et PHP-FPM, la faille de PHP2Shell se trouve dans PHP-FPM, pas dans Nginx. Corrigez toutes les versions de PHP-FPM, redémarrez complètement chaque service FPM et prouvez-le par les heures de démarrage des processus. Pour la sécurité Nginx PHP-FPM à long terme, ce sont des pools séparés, des valeurs non écrasables et une configuration Nginx qui n'exécute pas les fichiers envoyés qui comptent.

## Comment Nginx et PHP-FPM fonctionnent ensemble

Nginx sert lui-même les fichiers statiques et transmet les requêtes vers les scripts PHP à PHP-FPM via FastCGI. PHP-FPM se compose d'un processus maître et de plusieurs processus workers, regroupés en pools. Un worker traite successivement de nombreuses requêtes.

C'est précisément ce qui compte pour PHP2Shell. Avec CVE-2026-109619, l'état interne d'une requête peut subsister après la libération de la mémoire et être utilisé par une requête ultérieure dans le même worker. Avec CVE-2026-109618, un état de mémoire insuffisante (out-of-memory) peut interrompre PHP en pleine initialisation d'une requête. Les deux failles sont évaluées à CVSS v4.0 9.2 et corrigées dans PHP 8.5.12, 8.4.27, 8.3.36 et 8.2.35.

## Vérifier l'existant : versions, pools, processus

De nombreux serveurs ont plusieurs versions de PHP-FPM en parallèle. Les commandes suivantes se contentent de lire ; les noms de paquets et de services sont des exemples pour Debian/Ubuntu et la famille RHEL.

```bash
# Quels services FPM tournent ?
systemctl list-units --type=service | grep -i fpm

# Quelle version se cache derrière ? (exemple Debian/Ubuntu)
php-fpm8.3 -v
# Famille RHEL
php-fpm -v

# Vers quels sockets ou ports Nginx transmet-il ?
nginx -T 2>/dev/null | grep -E 'fastcgi_pass'

# Pools et leurs utilisateurs
grep -RhE '^\[|^user|^listen' /etc/php/*/fpm/pool.d/ 2>/dev/null
```

Faites correspondre chaque entrée `fastcgi_pass` avec un pool en service. Vous voyez ainsi quelle version de PHP dessert quel site. Pour les paquets de distribution, c'est le journal des modifications avec les numéros CVE qui prouve le correctif, et non le seul numéro de version.

Un constat fréquent lors de tels inventaires : des serveurs sur lesquels plusieurs versions de PHP ont été installées au fil des ans, dont une seule est réellement utilisée. Les autres services FPM continuent malgré tout de tourner, souvent avec des pools par défaut qui écoutent sur un socket ou un port local. Ils ne sont en général pas directement accessibles de l'extérieur, mais restent un risque inutile et allongent chaque mise à jour d'urgence. Désactivez et supprimez les versions qu'aucun site n'utilise, après avoir vérifié l'attribution via les entrées `fastcgi_pass`.

De même, un coup d'œil à l'utilisateur des pools s'impose. Si tous les pools tournent sous `www-data` ou `nginx`, la séparation entre les sites n'existe que sur le papier. Celui qui prend le contrôle d'un site peut alors lire les fichiers de tous les autres, par exemple les fichiers de configuration contenant des mots de passe de bases de données. Des utilisateurs système propres à chaque pool et des droits de fichiers adaptés créent ici une véritable frontière. Ce n'est pas un remède contre PHP2Shell, mais cela limite nettement les dégâts possibles d'une attaque réussie.

## Installer le correctif et renouveler tous les workers

Après la mise à jour des paquets, redémarrez chaque service PHP-FPM. Un rechargement remplace certes les workers, mais un redémarrage complet renouvelle aussi le processus maître et constitue la voie sûre après des mises à jour de sécurité.

```bash
# Exemple Debian/Ubuntu, pour chaque version installée
systemctl restart php8.3-fpm
# Famille RHEL
systemctl restart php-fpm

# Contrôle : heure de démarrage du maître et des workers
ps -eo pid,lstart,cmd | grep -E 'php-fpm' | grep -v grep
```

Chaque processus doit avoir été démarré après la mise à jour. Cela est décrit en détail sous [Redémarrer PHP-FPM et tous les workers](https://phpsos.de/fr/php2shell/php-fpm-neustart/).

> **Important:**
> Un correctif ne supprime pas les logiciels malveillants introduits auparavant. Conservez les journaux d'accès et d'erreurs de Nginx à partir du 20 octobre 2026 et recherchez des traces sur les sites.

## Définir les valeurs transitoires dans le pool

Tant qu'une version n'est pas corrigée, php.net recommande des mesures transitoires. Elles n'offrent pas de protection complète. Dans PHP-FPM, définissez les valeurs avec `php_admin_value` ou `php_admin_flag` dans le pool ; les applications ne peuvent alors pas les écraser avec `ini_set()`.

```ini
; Exemple : /etc/php/8.3/fpm/pool.d/website.conf
php_admin_flag[session.upload_progress.enabled] = off
php_admin_value[post_max_size] = 32M
php_admin_value[upload_max_filesize] = 24M
```

Sans fonction d'envoi de fichiers, php.net indique `post_max_size = 8M`. Sur PHP 8.5, `fatal_error_backtraces=0` s'y ajoute. Pour la recommandation relative à `memory_limit=-1`, il vous faut une limite de mémoire au niveau des cgroups, par exemple via `MemoryMax` dans un complément systemd pour le service FPM. Dans Nginx, adaptez `client_max_body_size` à la nouvelle `post_max_size`, afin que les utilisateurs reçoivent des messages d'erreur compréhensibles. Redémarrez ensuite FPM.

## Améliorer durablement la sécurité Nginx PHP-FPM

Au-delà du cas aigu, quelques règles de base aident à limiter les dégâts lors de futures failles :

- **Un pool par site**, avec son propre utilisateur système, son propre socket et sa propre limite `open_basedir`. Plus de détails sous [open_basedir et isolation par site](https://phpsos.de/fr/ratgeber/open-basedir/).
- **Droits des sockets** définis de sorte que seul Nginx puisse y accéder, aucun port FPM ouvert vers l'extérieur.
- **N'exécuter que les scripts existants :** dans la location PHP, définir `try_files $uri =404;`, afin que Nginx ne transmette pas à PHP des chemins qui n'existent pas.
- **Ne pas exécuter les fichiers envoyés :** interdire l'exécution de PHP dans les répertoires d'envoi. Des indications figurent sous [Mettre en œuvre des envois de fichiers sécurisés](https://phpsos.de/fr/ratgeber/datei-upload-sicher/).
- **Protéger les pages d'état :** rendre `pm.status_path` et `ping.path` accessibles uniquement en interne.

```nginx
# Exemple : aucune exécution de PHP dans le répertoire d'envoi
location ~* ^/uploads/.*\.php$ {
    deny all;
}
```

Vérifiez chaque modification avec `nginx -t` avant de recharger Nginx. Consignez en outre quels pools, versions et règles particulières existent sur le serveur. Cette courte documentation fait gagner un temps précieux lors de la prochaine faille critique, car personne n'a besoin de chercher d'abord quel site dépend de quel pool.

## Comment PHP SOS aide-t-il concrètement ?

- Nous associons chaque site à son pool et à sa version de PHP et vérifions l'état réel des paquets.
- Nous corrigeons, redémarrons tous les services FPM et documentons les heures de démarrage des processus comme justificatif.
- D'ici le correctif, nous définissons les valeurs transitoires par pool et limitons la mémoire par cgroup.
- Dans le cadre du [durcissement de serveur](https://phpsos.de/fr/leistungen/server-haertung/), nous séparons proprement pools, droits et répertoires d'envoi.
- En cas de soupçon d'intrusion, nous assurons la [réponse à incident](https://phpsos.de/fr/leistungen/incident-response/).


## Questions fréquentes

**Un systemctl reload suffit-il pour PHP-FPM après une mise à jour ?**  
Un rechargement renouvelle les workers, mais le processus maître peut conserver l'ancien code. Après une mise à jour de sécurité, un redémarrage complet du service est la voie sûre. Vérifiez ensuite l'heure de démarrage du maître et des workers.

**Faut-il redémarrer Nginx après une mise à jour de PHP ?**  
Nginx ne contient pas PHP lui-même et n'a pas besoin de redémarrer pour le correctif PHP. Ce sont tous les services PHP-FPM qui doivent redémarrer. Si vous modifiez en même temps la configuration de Nginx, vérifiez-la avec nginx -t avant de la recharger.

**Pourquoi des pools distincts pour chaque site ?**  
Chaque pool tourne avec son propre utilisateur et ses propres limites. Si un site est compromis, l'attaquant n'accède pas sans difficulté aux fichiers des autres. De plus, les valeurs transitoires peuvent être définies de façon ciblée pour chaque pool.

**pm.max_requests protège-t-il contre PHP2Shell ?**  
Non, il ne remplace pas un correctif. Cette valeur limite le nombre de requêtes qu'un worker traite avant d'être remplacé. Cela peut raccourcir la durée de vie des états dans le processus, mais ce n'est pas une mesure indiquée par php.net.

## Sources

- [php.net : avis de sécurité](https://www.php.net/)
- [PHP 8 ChangeLog](https://www.php.net/ChangeLog-8.php)
- [OWASP Cheat Sheets](https://cheatsheetseries.owasp.org/)
- [BSI : office fédéral allemand de la sécurité des technologies de l'information](https://www.bsi.bund.de/)
