# Sådan sikrer I Nginx med PHP-FPM

> Nginx PHP-FPM sikkerhed efter PHP2Shell: kontrollér pools og versioner, genstart alle workere, sæt midlertidige værdier med php_admin_value og hærd Nginx.

Kilde: https://phpsos.de/da/server/nginx-php-fpm/  
Status: 25.10.2026  
Udbyder: PHP SOS, PHP-nødhjælp og serversikkerhed. Akut hjælp på WhatsApp: https://wa.me/491736494914?text=Hej%20PHP%20SOS%2C%20vi%20har%20brug%20for%20hj%C3%A6lp%20med%20vores%20PHP-server.%20Firma%3A%20%E2%80%A6%20Website%3A%20%E2%80%A6

**Kort sagt:** Ved Nginx med PHP-FPM sidder sårbarheden fra PHP2Shell i PHP-FPM, ikke i Nginx. Patch alle PHP-FPM-versioner, genstart hver FPM-tjeneste fuldstændigt, og dokumenter det med processernes starttidspunkter. For Nginx PHP-FPM-sikkerheden på lang sigt tæller adskilte pools, værdier der ikke kan overskrives, og en Nginx-konfiguration, der ikke udfører uploadede filer.

## Hvordan Nginx og PHP-FPM arbejder sammen

Nginx leverer statiske filer selv og sender forespørgsler til PHP-scripts videre til PHP-FPM via FastCGI. PHP-FPM består af en master-proces og flere worker-processer, grupperet i pools. En worker behandler mange forespørgsler efter hinanden.

Netop det er relevant for PHP2Shell. Ved CVE-2026-109619 kan en forespørgsels interne tilstand efter frigivelse af hukommelsen blive stående og udnyttes af en senere forespørgsel i samme worker. Ved CVE-2026-109618 kan en out-of-memory-tilstand afbryde PHP midt i initialiseringen af en forespørgsel. Begge sårbarheder er vurderet til CVSS v4.0 9,2 og rettet i PHP 8.5.12, 8.4.27, 8.3.36 og 8.2.35.

## Kontrollér beholdningen: versioner, pools, processer

Mange servere har flere PHP-FPM-versioner side om side. Følgende kommandoer læser kun; pakke- og tjenestenavne er eksempler for Debian/Ubuntu og RHEL-familien.

```bash
# Hvilke FPM-tjenester kører?
systemctl list-units --type=service | grep -i fpm

# Hvilken version ligger bag? (eksempel Debian/Ubuntu)
php-fpm8.3 -v
# RHEL-familien
php-fpm -v

# Til hvilke sockets eller porte sender Nginx videre?
nginx -T 2>/dev/null | grep -E 'fastcgi_pass'

# Pools og deres brugere
grep -RhE '^\[|^user|^listen' /etc/php/*/fpm/pool.d/ 2>/dev/null
```

Afstem hver `fastcgi_pass`-post med en kørende pool. Så kan I se, hvilken PHP-version der betjener hvilket website. Ved distributionspakker er det ændringsloggen med CVE-numrene, der dokumenterer patchen, ikke versionsnummeret alene.

Et hyppigt fund ved sådanne optællinger er servere, hvor der gennem årene er installeret flere PHP-versioner, hvoraf kun én faktisk er i brug. De øvrige FPM-tjenester kører alligevel videre, ofte med standardpools, der lytter på en lokal socket eller port. De er udefra som regel ikke direkte tilgængelige, men er fortsat en unødig risiko og forlænger hver nødopdatering. Deaktivér og fjern versioner, som intet website bruger, efter at I har kontrolleret tildelingen via `fastcgi_pass`-posterne.

Ligeledes er det værd at se på poolenes bruger. Kører alle pools som `www-data` eller `nginx`, findes adskillelsen mellem websites kun på papiret. Den, der overtager ét website, kan så læse alle de andres filer, f.eks. konfigurationsfiler med databaseadgangskoder. Egne systembrugere pr. pool og passende filrettigheder skaber her en ægte grænse. Det er ingen afhjælpning af PHP2Shell, men begrænser tydeligt den mulige skade ved et vellykket angreb.

## Indspil patchen og forny alle workere

Efter pakkeopdateringen genstarter I hver PHP-FPM-tjeneste. En reload erstatter nok workerne, men en fuldstændig genstart fornyer også master-processen og er efter sikkerhedsopdateringer den sikre vej.

```bash
# Eksempel Debian/Ubuntu, pr. installeret version
systemctl restart php8.3-fpm
# RHEL-familien
systemctl restart php-fpm

# Kontrol: starttidspunkt for master og workere
ps -eo pid,lstart,cmd | grep -E 'php-fpm' | grep -v grep
```

Hver proces skal være startet efter opdateringen. Udførligt beskrevet står det under [Genstart PHP-FPM og alle workere](https://phpsos.de/da/php2shell/php-fpm-neustart/).

> **Vigtigt:**
> En patch fjerner ikke skadelig software, som blev smuglet ind tidligere. Gem Nginx' adgangs- og fejlprotokoller fra og med 20.10.2026, og undersøg websites for spor.

## Sæt midlertidige værdier i poolen

Så længe en version ikke er patchet, anbefaler php.net midlertidige foranstaltninger. De giver ikke fuldstændig beskyttelse. I PHP-FPM sætter I værdierne med `php_admin_value` henholdsvis `php_admin_flag` i poolen, så kan applikationer ikke overskrive dem via `ini_set()`.

```ini
; Eksempel: /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
```

Uden upload-funktion angiver php.net `post_max_size = 8M`. På PHP 8.5 kommer `fatal_error_backtraces=0` til. Til anvisningen om `memory_limit=-1` skal I bruge en hukommelsesgrænse på cgroup-niveau, f.eks. via `MemoryMax` i et systemd-tillæg til FPM-tjenesten. Tilpas i Nginx `client_max_body_size` til den nye `post_max_size`, så brugerne får forståelige fejlmeddelelser. Genstart derefter FPM.

## Forbedr Nginx PHP-FPM-sikkerheden varigt

Ud over det akutte tilfælde hjælper nogle grundregler, som begrænser skaden ved fremtidige sårbarheder:

- **Én pool pr. website** med egen systembruger, egen socket og egen `open_basedir`-grænse. Mere under [open_basedir og isolation pr. website](https://phpsos.de/da/ratgeber/open-basedir/).
- **Socket-rettigheder** sættes, så kun Nginx har adgang, og åbn ingen FPM-porte udad.
- **Udfør kun eksisterende scripts:** Sæt `try_files $uri =404;` i PHP-location, så Nginx ikke sender stier videre til PHP, som ikke findes.
- **Udfør ikke uploads:** Forbyd PHP-udførelse i upload-mapper. Henvisninger hertil står under [Implementér filupload sikkert](https://phpsos.de/da/ratgeber/datei-upload-sicher/).
- **Beskyt statussider:** Gør `pm.status_path` og `ping.path` kun tilgængelige internt.

```nginx
# Eksempel: ingen PHP-udførelse i upload-mappen
location ~* ^/uploads/.*\.php$ {
    deny all;
}
```

Kontrollér hver ændring med `nginx -t`, før I genindlæser Nginx. Noter desuden, hvilke pools, versioner og særregler der findes på serveren. Denne korte dokumentation sparer værdifuld tid ved den næste kritiske sårbarhed, fordi ingen først skal lede efter, hvilket website der hænger på hvilken pool.

## Hvordan hjælper PHP SOS konkret?

- Vi tildeler hvert website sin pool og PHP-version og kontrollerer den faktiske pakkestatus.
- Vi patcher, genstarter alle FPM-tjenester og dokumenterer processernes starttidspunkter som bevis.
- Indtil patchen er på plads, sætter vi de midlertidige værdier pr. pool og begrænser hukommelsen via cgroup.
- Som led i [serverhærdningen](https://phpsos.de/da/leistungen/server-haertung/) adskiller vi pools, rettigheder og upload-mapper ordentligt.
- Ved mistanke om et indbrud overtager vi [incident response](https://phpsos.de/da/leistungen/incident-response/).


## Ofte stillede spørgsmål

**Er systemctl reload nok for PHP-FPM efter en opdatering?**  
En reload fornyer workerne, men master-processen kan beholde den gamle kode. Efter en sikkerhedsopdatering er en fuldstændig genstart af tjenesten den sikre vej. Kontrollér bagefter starttidspunktet for master og workere.

**Skal Nginx genstartes efter en PHP-opdatering?**  
Nginx indeholder selv ikke PHP og behøver ikke genstartes for PHP-patchen. Genstartes skal alle PHP-FPM-tjenester. Ændrer I samtidig Nginx-konfigurationen, så kontrollér den med nginx -t, før I genindlæser.

**Hvorfor egne pools pr. website?**  
Hver pool kører med egen bruger og egne grænser. Bliver ét website kompromitteret, kommer angriberen ikke uden videre til de andres filer. Desuden kan midlertidige værdier sættes målrettet pr. pool.

**Er pm.max_requests en beskyttelse mod PHP2Shell?**  
Nej, det erstatter ikke en patch. Værdien begrænser, hvor mange forespørgsler en worker behandler, før den erstattes. Det kan forkorte tilstandes levetid i processen, men er ikke en afhjælpning, som php.net nævner.

## Kilder

- [php.net: Sikkerhedsmeddelelser](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/)
