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 →

Least privilege: de rechten van de webservergebruiker

Binnengesmokkelde code draait met de rechten van de webservergebruiker. Wat dit account mag, bepaalt hoe ver een aanvaller komt. Zo beperkt u shell, sudo, cron, database en bestandssysteem tot het noodzakelijke.

Stand 6 min. leestijdHardening en configuratie

Kort gezegd: De webservergebruiker waaronder PHP draait, hoort volgens het principe van minimale rechten (least privilege) alleen te lezen wat de website nodig heeft en alleen te schrijven waar de website gegevens opslaat. Hij heeft geen login-shell, geen sudo-rechten, geen eigen cronjobs en geen SSH-sleutels, en zijn databaseaccount mag alleen gegevens lezen en wijzigen. systemd-opties zoals ProtectSystem en PrivateTmp bakenen PHP-FPM extra af.

De vraag na de inbraak: wat mag dit proces?

Bij PHP2Shell gaat het om het op afstand uitvoeren van schadelijke code zonder inloggen. Lukt dat, dan draait de code niet in een luchtledige ruimte, maar als één bepaalde gebruiker: de gebruiker van het PHP-proces. Alles wat deze gebruiker mag, mag vanaf dat moment ook de aanvaller.

Op veel servers is dat verrassend veel. De gebruiker is eigenaar van alle programmacode, heeft een shell, kan eigen cronjobs aanmaken en het databaseaccount van de applicatie heeft alle rechten op alle databases. Voor een aanvaller is dat de ideale uitgangspositie om zich blijvend te nestelen.

Hoe u bestanden en mappen correct instelt, beschrijft de gids Bestandsrechten op de webserver. Dit artikel richt zich op het account zelf: aanmelding, bijzondere rechten, geplande taken, database en de grenzen die systemd trekt.

Inventarisatie: wie is de webservergebruiker?

Eerst stelt u vast welke gebruikers er eigenlijk bij betrokken zijn. Bij PHP-FPM bepaalt elke pool met user en group onder wie zijn workers draaien. Bij mod_php draait PHP als Apache-gebruiker. Hoe master en workers bij PHP-FPM samenwerken, legt PHP-FPM uitgelegd: procesmanager, pools en workers uit. De volgende opdrachten lezen alleen:

# Onder welke gebruikers draaien webserver en PHP?
ps -eo user,group,cmd | grep -E "[p]hp-fpm|[n]ginx|[a]pache2|[h]ttpd" | sort | uniq -c
# Accountgegevens: homedirectory en shell (gebruiker aanpassen)
getent passwd www-data
# Heeft de gebruiker sudo-rechten?
sudo -l -U www-data
# Eigen cronjobs?
sudo crontab -l -u www-data
# SSH-sleutels in de homedirectory (bij Debian/Ubuntu is dat /var/www)
sudo ls -la /var/www/.ssh 2>/dev/null

Noteer de resultaten voor elke poolgebruiker. Draaien alle websites onder dezelfde gebruiker, dan staat dat bovenaan de lijst; hoe u dat scheidt, beschrijft PHP-FPM-pools per website isoleren.

Rechten van de webservergebruiker: wat het account niet nodig heeft

Het volgende overzicht toont wat een webservergebruiker doorgaans niet nodig heeft en hoe u dat intrekt.

Recht Waarom gevaarlijk Aanbeveling
Login-shell Aanmelding en interactief gebruik mogelijk Shell /usr/sbin/nologin
sudo-regels Route naar rootrechten geen regels, ook niet voor losse opdrachten
eigen crontab blijvende achterdeur die elke herstart overleeft geen, beperken via /etc/cron.allow
SSH-sleutels Aanmelding van buitenaf geen authorized_keys
Eigendom van de programmacode Code kan worden gewijzigd Eigenaar is een deploygebruiker
Schrijfrechten buiten gegevensmappen Plaatsing van schadelijke code alleen uploads, cache, temp
volledige databaserechten Databases van andere applicaties, bestandstoegang via de database alleen de eigen database, alleen gegevensrechten

De shell stelt u in met usermod -s /usr/sbin/nologin www-data. Voor cron geldt: bestaat /etc/cron.allow, dan mogen alleen de daar genoemde gebruikers eigen cronjobs aanmaken. Nieuw aangemaakte cronjobs of onbekende SSH-sleutels zijn een typisch teken dat iemand zich heeft genesteld. Een bijzonder duidelijk waarschuwingssignaal beschrijft het artikel Waarschuwingssignaal: de webserver start een shell.

De database: rechten beperken tot het noodzakelijke

Het databaseaccount van een website is in feite een tweede webservergebruiker. De toegangsgegevens staan in het configuratiebestand van de applicatie en zijn leesbaar voor binnengesmokkelde code. Daarom mag het alleen doen wat de applicatie in bedrijf nodig heeft.

-- Voorbeeld MySQL/MariaDB: eigen account per website, alleen gegevensrechten
CREATE USER 'seite1'@'localhost' IDENTIFIED BY 'hier-ein-langes-Zufallspasswort';
GRANT SELECT, INSERT, UPDATE, DELETE ON seite1.* TO 'seite1'@'localhost';
-- Rechten controleren
SHOW GRANTS FOR 'seite1'@'localhost';

Rechten zoals FILE, SUPER of GRANT OPTION en toegang tot *.* heeft een applicatieaccount niet nodig. Veel CMS-systemen hebben voor updates aanvullend CREATE, ALTER, INDEX en DROP nodig. Netter is een apart account voor updates en migraties, dat alleen tijdens het onderhoud wordt gebruikt. Controleer de vereisten in de documentatie van de fabrikant.

PHP-FPM extra afbakenen met systemd

systemd kan een dienst beperken in zijn zicht op het systeem. Voor PHP-FPM zijn enkele opties uit de systemd-documentatie bijzonder geschikt. Ze werken ook op het masterproces, dat als root start.

# sudo systemctl edit php8.3-fpm
[Service]
# /usr, /boot en /etc alleen-lezen
ProtectSystem=full
# /home, /root en /run/user onzichtbaar
ProtectHome=true
# eigen /tmp en /var/tmp alleen voor deze dienst
PrivateTmp=true
# geen uitbreiding van rechten via setuid of bestands-capabilities
NoNewPrivileges=true

Test deze opties voordat u ze productief inzet. Staan websites onder /home, dan verhindert ProtectHome=true de toegang. NoNewPrivileges=true kan programma's hinderen die PHP aanroept en die bij het starten hun groepsrechten wisselen, zoals sommige lokale mailprogramma's voor de PHP-functie mail(). Ga daarom stapsgewijs te werk:

  1. Eén optie toevoegen, dienst herstarten, systemctl status php8.3-fpm controleren.
  2. Kernfuncties van de website testen: aanmelden, formulieren, mailverzending, uploads, cronjobs van de applicatie.
  3. Het foutenlogboek van PHP-FPM en van de applicatie beoordelen.
  4. Pas daarna de volgende optie toevoegen.

Tot slot de socket: volgens de PHP-handleiding krijgt die standaard de rechten 0660 voor gebruiker en groep van de pool. Stel listen.owner en listen.group zo in dat alleen de webserver kan verbinden, niet elke lokale gebruiker.

Tip

Minimale rechten zijn een basishouding, geen eenmalig project. Controleer de inventarisatie uit dit artikel na elke verbouwing en elke nieuwe website opnieuw, want nieuwe diensten brengen vaak ruimhartige standaardrechten mee.

Conclusie: de aanvaller erft wat u toestaat

Least privilege klinkt als theorie, maar is een heel praktische vraag: wat kan iemand doen die code als webservergebruiker uitvoert? Op een server met shell, sudo-regel, eigen crontab en een databaseaccount met alle rechten luidt het antwoord: bijna alles. Op een afgebakende server blijft het eerder bij een incident in één enkele website, dat te herkennen en op te schonen is.

De omschakeling vraagt geen nieuwe software, alleen een zorgvuldige inventarisatie en stapsgewijze tests. Begin met de punten die nauwelijks iets kunnen breken, dus shell, sudo en SSH-sleutels, en werk daarna toe naar databaserechten en systemd-opties.

Hoe helpt PHP SOS concreet?

  • Accounts controleren: Wij leggen voor elke pool en webserver gebruiker, shell, sudo-regels, cronjobs, SSH-sleutels en databaserechten vast.
  • Rechten verminderen: Wij trekken in wat niet nodig is en scheiden deploy-, runtime- en onderhoudsaccounts.
  • Diensten afbakenen: Wij zetten systemd-beschermingsopties stapsgewijs en testen de website na elke stap.
  • Blijvend vasthouden: In het kader van de serverhardening documenteren wij het rechtenconcept voor toekomstige wijzigingen.

Veelgestelde vragen

Onder welke gebruiker draait PHP op mijn server?

Dat hangt af van de bedrijfsmodus. Bij mod_php draait PHP als Apache-gebruiker, bijvoorbeeld www-data of apache. Bij PHP-FPM legt elke pool zijn gebruiker vast met user en group; het masterproces draait meestal als root, de workers als poolgebruiker. De opdracht ps laat dat snel zien.

Heeft de webservergebruiker een login-shell nodig?

Nee. Noch Nginx, noch Apache, noch PHP-FPM heeft een interactieve aanmelding voor deze gebruiker nodig. Een shell zoals /usr/sbin/nologin voorkomt dat iemand zich met dit account aanmeldt. Deployments lopen via een eigen gebruiker.

Waarom geen sudo-rechten voor www-data, ook niet voor één enkele opdracht?

Omdat binnengesmokkelde code precies deze rechten erft. Zelfs een ogenschijnlijk onschuldige opdracht kan, verkeerd vrijgegeven, tot rootrechten leiden. Taken die verhoogde rechten nodig hebben, horen thuis in aparte diensten of processen buiten de webserver.

Helpt dit tegen PHP2Shell?

Het dicht de kwetsbaarheid niet; daarvoor zijn de PHP-update en een herstart van alle workers nodig. Minimale rechten beperken wel wat een aanvaller na een geslaagde misbruikpoging kan doen: bestanden wijzigen, zich nestelen, andere websites bereiken.

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