# Nginx met PHP-FPM beveiligen

> Nginx PHP-FPM beveiliging na PHP2Shell: pools en versies controleren, alle workers herstarten, overbruggingswaarden via php_admin_value instellen en Nginx harden.

Bron: https://phpsos.de/nl/server/nginx-php-fpm/  
Stand: 25-10-2026  
Aanbieder: PHP SOS, PHP-noodhulp en serverbeveiliging. Directe hulp via WhatsApp: https://wa.me/491736494914?text=Hallo%20PHP%20SOS%2C%20wij%20hebben%20hulp%20nodig%20met%20onze%20PHP-server.%20Bedrijf%3A%20%E2%80%A6%20Website%3A%20%E2%80%A6

**Kort gezegd:** Bij Nginx met PHP-FPM zit de kwetsbaarheid van PHP2Shell in PHP-FPM, niet in Nginx. Patch alle PHP-FPM-versies, herstart elke FPM-dienst volledig en onderbouw dat met starttijden van processen. Voor een blijvende Nginx PHP-FPM beveiliging tellen gescheiden pools, niet-overschrijfbare waarden en een Nginx-configuratie die geen geüploade bestanden uitvoert.

## Hoe Nginx en PHP-FPM samenwerken

Nginx levert statische bestanden zelf uit en geeft verzoeken aan PHP-scripts via FastCGI door aan PHP-FPM. PHP-FPM bestaat uit een masterproces en meerdere workerprocessen, gegroepeerd in pools. Een worker handelt achter elkaar veel verzoeken af.

Precies dat is voor PHP2Shell relevant. Bij CVE-2026-109619 kan de interne toestand van een verzoek na het vrijgeven van het geheugen blijven bestaan en door een later verzoek in dezelfde worker worden gebruikt. Bij CVE-2026-109618 kan een out-of-memory-toestand PHP midden in de initialisatie van een verzoek onderbreken. Beide kwetsbaarheden zijn beoordeeld met CVSS v4.0 9.2 en verholpen in PHP 8.5.12, 8.4.27, 8.3.36 en 8.2.35.

## Inventaris controleren: versies, pools, processen

Veel servers hebben meerdere PHP-FPM-versies naast elkaar. De volgende opdrachten lezen alleen; pakket- en dienstnamen zijn voorbeelden voor Debian/Ubuntu en de RHEL-familie.

```bash
# Welke FPM-diensten draaien?
systemctl list-units --type=service | grep -i fpm

# Welke versie zit erachter? (voorbeeld Debian/Ubuntu)
php-fpm8.3 -v
# RHEL-familie
php-fpm -v

# Naar welke sockets of poorten geeft Nginx door?
nginx -T 2>/dev/null | grep -E 'fastcgi_pass'

# Pools en hun gebruikers
grep -RhE '^\[|^user|^listen' /etc/php/*/fpm/pool.d/ 2>/dev/null
```

Vergelijk elke `fastcgi_pass`-vermelding met een draaiende pool. Zo ziet u welke PHP-versie welke website bedient. Bij distributiepakketten onderbouwt het wijzigingslogboek met de CVE-nummers de patch, niet het versienummer alleen.

Een veelvoorkomende bevinding bij zulke inventarisaties zijn servers waarop in de loop der jaren meerdere PHP-versies zijn geïnstalleerd, waarvan er maar één echt in gebruik is. De overige FPM-diensten blijven toch draaien, vaak met standaardpools die luisteren op een lokale socket of poort. Ze zijn van buitenaf meestal niet rechtstreeks bereikbaar, maar blijven een onnodig risico en verlengen elke noodupdate. Schakel versies die geen enkele website gebruikt uit en verwijder ze, nadat u de toewijzing via de `fastcgi_pass`-vermeldingen hebt gecontroleerd.

Ook loont een blik op de gebruiker van de pools. Draaien alle pools als `www-data` of `nginx`, dan bestaat de scheiding tussen de websites alleen op papier. Wie één website overneemt, kan dan de bestanden van alle andere lezen, bijvoorbeeld configuratiebestanden met databasewachtwoorden. Eigen systeemgebruikers per pool en passende bestandsrechten scheppen hier een echte grens. Dat is geen oplossing voor PHP2Shell, maar het beperkt de mogelijke schade van een geslaagde aanval aanzienlijk.

## Patch doorvoeren en alle workers vernieuwen

Herstart na de pakketupdate elke PHP-FPM-dienst. Een reload vervangt weliswaar de workers, maar een volledige herstart vernieuwt ook het masterproces en is na beveiligingsupdates de veilige weg.

```bash
# Voorbeeld Debian/Ubuntu, per geïnstalleerde versie
systemctl restart php8.3-fpm
# RHEL-familie
systemctl restart php-fpm

# Controle: starttijd van master en workers
ps -eo pid,lstart,cmd | grep -E 'php-fpm' | grep -v grep
```

Elk proces moet na de update zijn gestart. Uitvoerig beschreven staat dat onder [PHP-FPM en alle workers herstarten](https://phpsos.de/nl/php2shell/php-fpm-neustart/).

> **Belangrijk:**
> Een patch verwijdert geen schadelijke software die eerder is ingebracht. Bewaar de toegangs- en foutlogs van Nginx vanaf 20-10-2026 en controleer de websites op sporen.

## Overbruggingswaarden in de pool instellen

Zolang een versie niet is gepatcht, adviseert php.net overbruggingsmaatregelen. Ze bieden geen volledige bescherming. In PHP-FPM stelt u de waarden in met `php_admin_value` respectievelijk `php_admin_flag` in de pool, dan kunnen toepassingen ze niet via `ini_set()` overschrijven.

```ini
; Voorbeeld: /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
```

Zonder uploadfunctie noemt php.net `post_max_size = 8M`. Op PHP 8.5 komt `fatal_error_backtraces=0` erbij. Voor de aanwijzing over `memory_limit=-1` hebt u een geheugengrens op cgroup-niveau nodig, bijvoorbeeld via `MemoryMax` in een systemd-aanvulling voor de FPM-dienst. Pas in Nginx `client_max_body_size` aan op de nieuwe `post_max_size`, zodat gebruikers begrijpelijke foutmeldingen krijgen. Herstart daarna FPM.

## Nginx PHP-FPM beveiliging duurzaam verbeteren

Naast het acute geval helpen enkele basisregels die de schade bij toekomstige kwetsbaarheden beperken:

- **Eén pool per website** met een eigen systeemgebruiker, eigen socket en eigen `open_basedir`-grens. Meer onder [open_basedir en isolatie per website](https://phpsos.de/nl/ratgeber/open-basedir/).
- **Socketrechten** zo instellen dat alleen Nginx erbij kan, geen FPM-poorten naar buiten openen.
- **Alleen bestaande scripts uitvoeren:** zet in de PHP-location `try_files $uri =404;`, zodat Nginx geen paden aan PHP doorgeeft die niet bestaan.
- **Uploads niet uitvoeren:** verbied PHP-uitvoering in uploadmappen. Aanwijzingen daarvoor staan onder [Bestandsuploads veilig implementeren](https://phpsos.de/nl/ratgeber/datei-upload-sicher/).
- **Statuspagina's beschermen:** maak `pm.status_path` en `ping.path` alleen intern bereikbaar.

```nginx
# Voorbeeld: geen PHP-uitvoering in de uploadmap
location ~* ^/uploads/.*\.php$ {
    deny all;
}
```

Controleer elke wijziging met `nginx -t` voordat u Nginx herlaadt. Leg bovendien vast welke pools, versies en bijzondere regels er op de server bestaan. Deze korte documentatie bespaart bij de volgende kritieke kwetsbaarheid kostbare tijd, omdat niemand eerst hoeft uit te zoeken welke website bij welke pool hoort.

## Hoe helpt PHP SOS concreet?

- Wij koppelen elke website aan haar pool en PHP-versie en controleren de werkelijke pakketstatus.
- Wij patchen, herstarten alle FPM-diensten en documenteren starttijden van processen als bewijs.
- Tot de patch stellen we de overbruggingswaarden per pool in en beperken we het geheugen via cgroup.
- In het kader van de [serverhardening](https://phpsos.de/nl/leistungen/server-haertung/) scheiden we pools, rechten en uploadmappen netjes.
- Bij vermoeden van een inbraak nemen we de [Incident Response](https://phpsos.de/nl/leistungen/incident-response/) over.


## Veelgestelde vragen

**Volstaat systemctl reload voor PHP-FPM na een update?**  
Een reload vernieuwt de workers, maar het masterproces kan de oude code behouden. Na een beveiligingsupdate is een volledige herstart van de dienst de veilige weg. Controleer daarna de starttijd van master en workers.

**Moet Nginx na een PHP-update worden herstart?**  
Nginx zelf bevat geen PHP en hoeft voor de PHP-patch niet te herstarten. Herstarten moeten alle PHP-FPM-diensten. Wijzigt u daarbij de Nginx-configuratie, controleer die dan vóór het herladen met nginx -t.

**Waarom aparte pools per website?**  
Elke pool draait met een eigen gebruiker en eigen grenzen. Wordt één website gecompromitteerd, dan komt de aanvaller niet zomaar bij de bestanden van de andere. Bovendien kunt u overbruggingswaarden gericht per pool instellen.

**Is pm.max_requests een bescherming tegen PHP2Shell?**  
Nee, het vervangt geen patch. De waarde begrenst hoeveel verzoeken een worker afhandelt voordat hij wordt vervangen. Dat kan de levensduur van toestanden in het proces verkorten, maar is geen door php.net genoemde oplossing.

## Bronnen

- [php.net: beveiligingsmeldingen](https://www.php.net/)
- [PHP 8 ChangeLog](https://www.php.net/ChangeLog-8.php)
- [OWASP Cheat Sheets](https://cheatsheetseries.owasp.org/)
- [BSI](https://www.bsi.bund.de/)
