# Least Privilege: Rechte des Webserver-Benutzers

> Webserver-Benutzer mit minimalen Rechten: keine Shell, kein sudo, kein Cron, knappe Datenbankrechte und systemd-Schutz für PHP-FPM. Mit Prüfbefehlen.

Quelle: https://phpsos.de/blog/rechte-des-webserver-benutzers/  
Stand: 25.10.2026  
Anbieter: PHP SOS, PHP-Notfallhilfe und Server-Sicherheit. Soforthilfe per WhatsApp: https://wa.me/491736494914?text=Hallo%20PHP%20SOS%2C%20wir%20brauchen%20Hilfe%20mit%20unserem%20PHP-Server.%20Firma%3A%20%E2%80%A6%20Website%3A%20%E2%80%A6

**Kurz gesagt:** Der Webserver-Benutzer, unter dem PHP läuft, sollte nach dem Prinzip der minimalen Rechte (Least Privilege) nur lesen, was die Website braucht, und nur dort schreiben, wo sie Daten ablegt. Er hat keine Login-Shell, keine sudo-Rechte, keine eigenen Cronjobs und keine SSH-Schlüssel, und sein Datenbankkonto darf nur Daten lesen und ändern. systemd-Optionen wie `ProtectSystem` und `PrivateTmp` grenzen PHP-FPM zusätzlich ein.

## Die Frage nach dem Einbruch: Was darf dieser Prozess?

Bei PHP2Shell geht es um die Ausführung von Schadcode aus der Ferne ohne Anmeldung. Gelingt sie, läuft der Code nicht im luftleeren Raum, sondern als ein ganz bestimmter Benutzer: der Benutzer des PHP-Prozesses. Alles, was dieser Benutzer darf, darf von diesem Moment an auch der Angreifer.

Auf vielen Servern ist das erstaunlich viel. Der Benutzer besitzt den gesamten Programmcode, hat eine Shell, kann eigene Cronjobs anlegen, und das Datenbankkonto der Anwendung hat alle Rechte auf alle Datenbanken. Für einen Angreifer ist das die ideale Ausgangslage, um sich dauerhaft einzurichten.

Wie Sie Dateien und Ordner richtig vergeben, beschreibt der Ratgeber [Dateirechte auf dem Webserver](https://phpsos.de/ratgeber/dateirechte-webserver/). Dieser Beitrag nimmt das Konto selbst in den Blick: Anmeldung, Sonderrechte, geplante Aufgaben, Datenbank und die Grenzen, die systemd zieht.

## Bestandsaufnahme: Wer ist der Webserver-Benutzer?

Zuerst klären Sie, welche Benutzer überhaupt beteiligt sind. Bei PHP-FPM legt jeder Pool mit `user` und `group` fest, unter wem seine Worker laufen. Bei mod_php läuft PHP als Apache-Benutzer. Wie Master und Worker bei PHP-FPM zusammenspielen, erklärt [PHP-FPM erklärt: Prozessmanager, Pools und Worker](https://phpsos.de/php/php-fpm-erklaert/). Die folgenden Befehle lesen nur:

```bash
# Unter welchen Benutzern laufen Webserver und PHP?
ps -eo user,group,cmd | grep -E "[p]hp-fpm|[n]ginx|[a]pache2|[h]ttpd" | sort | uniq -c
# Kontoangaben: Home-Verzeichnis und Shell (Benutzer anpassen)
getent passwd www-data
# Hat der Benutzer sudo-Rechte?
sudo -l -U www-data
# Eigene Cronjobs?
sudo crontab -l -u www-data
# SSH-Schlüssel im Home-Verzeichnis (bei Debian/Ubuntu ist das /var/www)
sudo ls -la /var/www/.ssh 2>/dev/null
```

Notieren Sie die Ergebnisse für jeden Pool-Benutzer. Laufen alle Websites unter demselben Benutzer, ist das der erste Punkt auf der Liste; wie Sie das trennen, beschreibt [PHP-FPM-Pools pro Website isolieren](https://phpsos.de/blog/php-fpm-pools-isolieren/).

## Webserver-Benutzer-Rechte: Was das Konto nicht braucht

Die folgende Übersicht zeigt, was ein Webserver-Benutzer typischerweise nicht braucht und wie Sie es entziehen.

| Recht | Warum gefährlich | Empfehlung |
|---|---|---|
| Login-Shell | Anmeldung und interaktive Nutzung möglich | Shell `/usr/sbin/nologin` |
| sudo-Einträge | Weg zu Root-Rechten | keine Einträge, auch nicht für Einzelbefehle |
| eigene Crontab | dauerhafte Hintertür, die jeden Neustart überlebt | keine, per `/etc/cron.allow` begrenzen |
| SSH-Schlüssel | Anmeldung von außen | keine `authorized_keys` |
| Besitz des Programmcodes | Code kann verändert werden | Eigentümer ist ein Deploy-Benutzer |
| Schreibrechte außerhalb von Daten-Ordnern | Ablage von Schadcode | nur Uploads, Cache, Temp |
| volle Datenbankrechte | Datenbanken anderer Anwendungen, Dateizugriff über die Datenbank | nur die eigene Datenbank, nur Datenrechte |

Die Shell setzen Sie mit `usermod -s /usr/sbin/nologin www-data`. Für Cron gilt: Existiert `/etc/cron.allow`, dürfen nur die dort genannten Benutzer eigene Cronjobs anlegen. Neu angelegte Cronjobs oder unbekannte SSH-Schlüssel sind ein typisches Zeichen dafür, dass sich jemand festgesetzt hat. Ein besonders deutliches Warnsignal beschreibt der Beitrag [Warnsignal: Der Webserver startet eine Shell](https://phpsos.de/blog/webserver-startet-shell/).

## Die Datenbank: Rechte auf das Nötige begrenzen

Das Datenbankkonto einer Website ist faktisch ein zweiter Webserver-Benutzer. Seine Zugangsdaten liegen in der Konfigurationsdatei der Anwendung und sind für eingeschleusten Code lesbar. Deshalb sollte es nur das dürfen, was die Anwendung im Betrieb braucht.

```sql
-- Beispiel MySQL/MariaDB: eigenes Konto je Website, nur Datenrechte
CREATE USER 'seite1'@'localhost' IDENTIFIED BY 'hier-ein-langes-Zufallspasswort';
GRANT SELECT, INSERT, UPDATE, DELETE ON seite1.* TO 'seite1'@'localhost';
-- Rechte prüfen
SHOW GRANTS FOR 'seite1'@'localhost';
```

Rechte wie `FILE`, `SUPER` oder `GRANT OPTION` und Zugriff auf `*.*` hat ein Anwendungskonto nicht nötig. Viele CMS brauchen für Updates zusätzlich `CREATE`, `ALTER`, `INDEX` und `DROP`. Sauberer ist ein getrenntes Konto für Updates und Migrationen, das nur während der Wartung genutzt wird. Prüfen Sie die Anforderungen in der Dokumentation des Herstellers.

## PHP-FPM mit systemd zusätzlich eingrenzen

systemd kann einen Dienst in seiner Sicht auf das System beschränken. Für PHP-FPM eignen sich einige Optionen aus der systemd-Dokumentation besonders. Sie wirken auch auf den Master-Prozess, der als root startet.

```ini
# sudo systemctl edit php8.3-fpm
[Service]
# /usr, /boot und /etc schreibgeschützt
ProtectSystem=full
# /home, /root und /run/user unsichtbar
ProtectHome=true
# eigenes /tmp und /var/tmp nur für diesen Dienst
PrivateTmp=true
# keine Rechteerweiterung über setuid oder Datei-Capabilities
NoNewPrivileges=true
```

Testen Sie diese Optionen vor dem produktiven Einsatz. Liegen Websites unter `/home`, verhindert `ProtectHome=true` den Zugriff. `NoNewPrivileges=true` kann Programme stören, die PHP aufruft und die beim Start ihre Gruppenrechte wechseln, etwa manche lokalen Mailprogramme für die PHP-Funktion `mail()`. Gehen Sie deshalb in Schritten vor:

1. Eine Option ergänzen, Dienst neu starten, `systemctl status php8.3-fpm` prüfen.
2. Kernfunktionen der Website testen: Anmeldung, Formulare, Mailversand, Uploads, Cronjobs der Anwendung.
3. Das Fehlerlog von PHP-FPM und der Anwendung auswerten.
4. Erst dann die nächste Option ergänzen.

Zum Schluss der Socket: Laut PHP-Handbuch erhält er standardmäßig Rechte `0660` für Benutzer und Gruppe des Pools. Setzen Sie `listen.owner` und `listen.group` so, dass nur der Webserver verbinden kann, nicht jeder lokale Benutzer.

> **Tipp:**
> Minimale Rechte sind eine Grundhaltung, kein einmaliges Projekt. Prüfen Sie die Bestandsaufnahme aus diesem Beitrag nach jedem Umbau und jeder neuen Website erneut, denn neue Dienste bringen oft großzügige Standardrechte mit.

## Fazit: Der Angreifer erbt, was Sie erlauben

Least Privilege klingt nach Theorie, ist aber eine sehr praktische Frage: Was kann jemand tun, der Code als Webserver-Benutzer ausführt? Auf einem Server mit Shell, sudo-Eintrag, eigener Crontab und einem Datenbankkonto mit allen Rechten lautet die Antwort: fast alles. Auf einem eingegrenzten Server bleibt es eher bei einem Vorfall in einer einzelnen Website, der sich erkennen und bereinigen lässt.

Die Umstellung braucht keine neue Software, nur eine sorgfältige Bestandsaufnahme und schrittweise Tests. Beginnen Sie mit den Punkten, die kaum etwas brechen können, also Shell, sudo und SSH-Schlüssel, und arbeiten Sie sich dann zu Datenbankrechten und systemd-Optionen vor.

## Wie hilft PHP SOS konkret?

- **Konten prüfen:** Wir erfassen für jeden Pool und Webserver Benutzer, Shell, sudo-Einträge, Cronjobs, SSH-Schlüssel und Datenbankrechte.
- **Rechte reduzieren:** Wir entziehen, was nicht gebraucht wird, und trennen Deploy-, Laufzeit- und Wartungskonten.
- **Dienste eingrenzen:** Wir setzen systemd-Schutzoptionen schrittweise und testen die Website nach jedem Schritt.
- **Dauerhaft halten:** Im Rahmen der [Server-Härtung](https://phpsos.de/leistungen/server-haertung/) dokumentieren wir das Rechtekonzept für künftige Änderungen.


## Häufige Fragen

**Unter welchem Benutzer läuft PHP auf meinem Server?**  
Das hängt von der Betriebsart ab. Bei mod_php läuft PHP als Apache-Benutzer, etwa www-data oder apache. Bei PHP-FPM legt jeder Pool seinen Benutzer mit user und group fest; der Master-Prozess läuft meist als root, die Worker als Pool-Benutzer. Der Befehl ps zeigt das schnell.

**Braucht der Webserver-Benutzer eine Login-Shell?**  
Nein. Weder Nginx noch Apache noch PHP-FPM brauchen eine interaktive Anmeldung für diesen Benutzer. Eine Shell wie /usr/sbin/nologin verhindert, dass sich jemand mit diesem Konto anmeldet. Deployments laufen über einen eigenen Benutzer.

**Warum keine sudo-Rechte für www-data, auch nicht für einen einzigen Befehl?**  
Weil eingeschleuster Code genau diese Rechte erbt. Schon ein scheinbar harmloser Befehl kann, falsch freigegeben, zu Root-Rechten führen. Aufgaben, die erhöhte Rechte brauchen, gehören in getrennte Dienste oder Abläufe außerhalb des Webservers.

**Hilft das gegen PHP2Shell?**  
Es schließt die Lücke nicht, dafür braucht es das PHP-Update und den Neustart aller Worker. Minimale Rechte begrenzen aber, was ein Angreifer nach einer erfolgreichen Ausnutzung tun kann: Dateien ändern, sich festsetzen, andere Websites erreichen.

## Quellen

- [PHP-Handbuch: FPM-Konfiguration (user, listen.mode)](https://www.php.net/manual/en/install.fpm.configuration.php)
- [systemd.exec (ProtectSystem, PrivateTmp, NoNewPrivileges)](https://www.freedesktop.org/software/systemd/man/latest/systemd.exec.html)
- [BSI IT-Grundschutz](https://www.bsi.bund.de/DE/Themen/Unternehmen-und-Organisationen/Standards-und-Zertifizierung/IT-Grundschutz/it-grundschutz_node.html)
- [OWASP Cheat Sheets](https://cheatsheetseries.owasp.org/)
