Kort gezegd: Voor beheerders zonder ontwikkelachtergrond volstaan vijf basisprincipes om PHP veilig te laten draaien: PHP bestaat uit meerdere programma's (opdrachtregel, PHP-FPM, Apache-module) met elk een eigen versie; instellingen werken in niveaus van de php.ini tot de toepassing; PHP-FPM verdeelt verzoeken over workers in pools; een update werkt pas na de herstart van alle processen; en logs zijn de belangrijkste aanwijzing wanneer er iets niet klopt. Wie deze punten kent, kan lekken zoals PHP2Shell snel en aantoonbaar dichten.
Waaruit PHP op een server bestaat
PHP is geen enkel programma. Op een typische Linux-server vindt men meerdere varianten, die elk via een serverinterface (SAPI) zijn aangesloten:
| Variant | Typische naam | Waarvoor |
|---|---|---|
| Opdrachtregel (CLI) | php, php8.3 |
cronjobs, Composer, onderhoudsscripts |
| PHP-FPM | php-fpm, php-fpm8.3 |
webverzoeken achter Nginx of Apache |
| Apache-module | mod_php, libphp |
webverzoeken rechtstreeks in het Apache-proces |
| CGI | php-cgi |
oudere opstellingen |
Elke variant kan een andere versie en een andere php.ini hebben. Op veel servers draaien bovendien meerdere PHP-versies parallel, bijvoorbeeld 8.2 en 8.4. Bij een update moet elke versie afzonderlijk worden bekeken. Hoe de interfaces werken, legt PHP-FPM uitgelegd uit.
Welke variant uw websites daadwerkelijk bedient, vindt u via de lopende processen en de webserverconfiguratie:
ps -eo pid,user,lstart,cmd | grep -E "php|httpd|apache2" | grep -v grep
apachectl -M 2>/dev/null | grep -i php # laadt Apache een PHP-module?
ls /run/php/ 2>/dev/null # FPM-sockets, vaak per versie en pool
De kolom met de starttijd is later bij de herstart belangrijk: alle PHP-processen moeten na het tijdstip van de update zijn gestart. Draaien processen onder verschillende gebruikers, dan wijst dat op gescheiden pools, wat goed is. Verschijnt er een PHP-module in Apache terwijl alle websites via FPM zouden moeten lopen, dan is dat een aanwijzing voor een erfenis uit het verleden die verwijderd hoort te worden. Voor hostingomgevingen zoals Plesk of cPanel geldt hetzelfde principe, alleen toont de interface de versies en handlers per website; bepalend blijft echter wat er daadwerkelijk als proces draait.
De belangrijkste opdrachten voor beheerders
php -v # versie van de opdrachtregel
php --ini # geladen php.ini en extra gelezen mappen
php --ini=diff # vanaf PHP 8.5: afwijkingen van de standaard
php -m # ingecompileerde en geladen modules
php --ri session # instellingen van een extensie
php -l datei.php # syntaxcontrole zonder uitvoering
php-fpm8.3 -v # versie van de FPM-binary (naam per distributie)
php-fpm8.3 -t # FPM-configuratie testen, zonder opnieuw te starten
systemctl status php8.3-fpm
Twee aanwijzingen uit de handleiding: php -l vindt syntaxfouten, maar geen fouten die pas tijdens de uitvoering optreden. En php -i roept phpinfo() aan; de uitvoer hoort niet in openbare bestanden in de webmap.
Hoe PHP-instellingen werken
Een instelling kan op meerdere plaatsen worden gezet. Wie waar wat mag wijzigen, regelt de wijzigingsmodus van elke directive:
- php.ini en conf.d: basisconfiguratie per variant, gelezen bij de start.
- FPM-pool:
php_valueenphp_admin_valueper pool. Metphp_admin_valuegezette waarden kan de toepassing volgens de handleiding niet viaini_set()overschrijven. - Mapniveau:
.user.inibij FPM of.htaccessbij mod_php, alleen voor directives in de modusINI_PERDIRofINI_ALL. - Toepassing:
ini_set()tijdens de uitvoering, alleen voor directives in de modusINI_ALL.
Een voorbeeld: memory_limit heeft de modus INI_ALL, kan dus door de toepassing worden gewijzigd. post_max_size heeft INI_PERDIR en laat zich niet via ini_set() wijzigen. Daarom eist php.net bij de PHP2Shell-overgangsmaatregelen dat waarden zo worden gezet dat toepassingen ze niet kunnen overschrijven. Details over de niveaus legt De php.ini uitgelegd uit.
PHP-FPM-pools in het kort
Een pool is een groep workers met eigen gebruiker, eigen socket en eigen instellingen. De belangrijkste directives volgens de handleiding:
[shop]
user = shop
group = shop
listen = /run/php/shop.sock
pm = dynamic ; static, dynamic of ondemand
pm.max_children = 20 ; hoogstens 20 gelijktijdige verzoeken
pm.max_requests = 500 ; worker na 500 verzoeken vernieuwen
request_slowlog_timeout = 5s
slowlog = /var/log/php-fpm/shop-slow.log
php_admin_value[error_log] = /var/log/php-fpm/shop-error.log
php_admin_flag[log_errors] = on
Een eigen pool per website met een eigen gebruiker scheidt websites van elkaar. security.limit_extensions staat standaard op .php .phar en voorkomt dat FPM andere bestandsextensies dan PHP uitvoert. clear_env is standaard ingeschakeld en houdt omgevingsvariabelen bij de worker vandaan.
Logs: waar beheerders naar kijken
PHP schrijft fouten naar het met error_log vastgelegde doel, PHP-FPM bovendien naar zijn eigen log en bij trage verzoeken naar het slowlog met backtrace. Daarbij komen de toegangs- en foutlogs van de webserver. Let erop dat display_errors in productie is uitgeschakeld en log_errors is ingeschakeld: fouten horen in het log, niet op de webpagina. Logs moeten bovendien worden geroteerd en gedurende een vastgelegde periode bewaard, zodat ze er in een noodgeval nog zijn. Na PHP2Shell adviseert de vakpers serverlogs vanaf 20 oktober 2026 te bewaren. Een sterk waarschuwingssignaal is een PHP-FPM- of webserverproces dat een shell start; hoe u dat herkent, staat onder Waarschuwingssignaal: de webserver start een shell.
Checklist voor beheerders na PHP2Shell
- Alle PHP-varianten en -versies op de server opsommen, ook de niet gebruikte.
- Pakketstand controleren; bij backports van de distributie de changelog doorzoeken op CVE-2026-109618 en CVE-2026-109619.
- Bijwerken naar 8.5.12, 8.4.27, 8.3.36 of 8.2.35, respectievelijk de bevestigde backport.
- PHP-FPM, Apache en LiteSpeed opnieuw starten en starttijden van de processen controleren.
- Tegenproef met
php -r 'var_dump(ini_get("memory_hard_limit_percent"));';bool(false)betekent volgens de handleiding een getroffen versie. - Logs veiligstellen en op bijzonderheden controleren.
Hoe u versie en patchstatus betrouwbaar aantoont, beschrijft PHP-versie en patchstatus goed controleren.
Hoe helpt PHP SOS concreet?
In het security-onderhoudscontract nemen wij het PHP-basisonderhoud met uw team over:
- Inventaris: alle PHP-varianten, versies, pools en configuratielocaties per server.
- Configuratie: beveiligingsrelevante waarden met
php_admin_valuegezet, pools per website gescheiden. - Updates: doorvoeren, herstarten, controleren en documenteren bij elke beveiligingsrelease.
- Kennis overdragen: Wij leggen uw beheerders uit wat wij hebben gewijzigd en waarom.
Veelgestelde vragen
Waarom toont php -v een andere versie dan de website?
Opdrachtregel, PHP-FPM en Apache-module zijn afzonderlijke programma's met eigen versie en eigen php.ini. php -v toont alleen de opdrachtregel. Voor de website telt de versie van de binary die daadwerkelijk verzoeken afhandelt.
Welke php.ini geldt op mijn server?
Dat toont php --ini voor de opdrachtregel. Voor PHP-FPM is er meestal een eigen php.ini en zijn er extra poolbestanden. Sinds PHP 8.5 toont php --ini=diff welke waarden van de standaard afwijken.
Wat is het verschil tussen php_value en php_admin_value?
Beide stellen instellingen in binnen een FPM-pool. Waarden met php_admin_value kan de toepassing volgens de handleiding niet met ini_set() overschrijven. Voor beveiligingsrelevante instellingen is php_admin_value daarom de juiste keuze.
Volstaat een update zonder herstart?
Nee. Lopende PHP-processen houden de oude code in het geheugen. Na een update moeten PHP-FPM, Apache met mod_php of LiteSpeed opnieuw worden gestart, anders blijft de kwetsbare versie draaien.