Actuele situatie: PHP2Shell. Twee kritieke PHP-kwetsbaarheden (CVSS 9.2) maken schadelijke code zonder inloggen mogelijk. Patches sinds 21-10-2026.Wat u nu moet doen →

Nginx met PHP-FPM beveiligen

Bij Nginx met PHP-FPM zit de beveiliging in pools, rechten en een nette herstart. Zo patcht u na PHP2Shell en harden u Nginx en PHP-FPM duurzaam.

Stand 5 min. leestijdServer & hosting

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.

# 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.

# 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.

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.

; 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.
  • 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.
  • Statuspagina's beschermen: maak pm.status_path en ping.path alleen intern bereikbaar.
# 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 scheiden we pools, rechten en uploadmappen netjes.
  • Bij vermoeden van een inbraak nemen we de 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

Direct contact

Elk uur telt. Schrijf ons nu.

Beschrijf kort het systeem, de PHP-versie en wat u opmerkt. Wij nemen contact op, brengen de situatie in kaart en werken op afstand tot het incident is afgerond en gedocumenteerd.

Directe hulp