# Least Privilege: oprávnění uživatele webserveru

> Uživatel webserveru s minimálními právy: bez shellu, sudo a cronu, s úzkými právy k databázi a ochranou systemd pro PHP-FPM. S kontrolními příkazy.

Zdroj: https://phpsos.de/cs/blog/rechte-des-webserver-benutzers/  
Stav: 25.10.2026  
Poskytovatel: PHP SOS, Nouzová pomoc pro PHP a bezpečnost serverů. Okamžitá pomoc přes WhatsApp: https://wa.me/491736494914?text=Dobr%C3%BD%20den%2C%20PHP%20SOS%2C%20pot%C5%99ebujeme%20pomoc%20s%20na%C5%A1%C3%ADm%20PHP%20serverem.%20Firma%3A%20%E2%80%A6%20Web%3A%20%E2%80%A6

**Stručně:** Uživatel webserveru, pod kterým běží PHP, by měl podle principu nejmenších oprávnění (Least Privilege) číst jen to, co web potřebuje, a zapisovat jen tam, kam ukládá data. Nemá přihlašovací shell, práva sudo, vlastní cronjoby ani klíče SSH a jeho účet v databázi smí data jen číst a měnit. Volby systemd jako `ProtectSystem` a `PrivateTmp` PHP-FPM navíc omezují.

## Otázka po průniku: co smí tento proces?

U PHP2Shell jde o spuštění škodlivého kódu na dálku bez přihlášení. Pokud se to podaří, kód neběží v prázdnu, ale pod konkrétním uživatelem: uživatelem procesu PHP. Vše, co tento uživatel smí, smí od té chvíle i útočník.

Na mnoha serverech je to překvapivě hodně. Uživatel vlastní veškerý programový kód, má shell, může zakládat vlastní cronjoby a databázový účet aplikace má všechna práva ke všem databázím. Pro útočníka je to ideální výchozí pozice, aby se na serveru trvale usadil.

Jak správně přidělit práva k souborům a složkám, popisuje příručka [Oprávnění k souborům na webserveru](https://phpsos.de/cs/ratgeber/dateirechte-webserver/). Tento článek se zaměřuje na samotný účet: přihlášení, zvláštní práva, plánované úlohy, databázi a hranice, které vymezuje systemd.

## Inventura: kdo je uživatel webserveru?

Nejprve zjistěte, kteří uživatelé se vůbec podílejí. U PHP-FPM určuje každý pool pomocí `user` a `group`, pod kým běží jeho workery. U mod_php běží PHP jako uživatel Apache. Jak spolupracují master a workery u PHP-FPM, vysvětluje stránka [PHP-FPM vysvětleno: správce procesů, pooly a workeři](https://phpsos.de/cs/php/php-fpm-erklaert/). Následující příkazy jen čtou:

```bash
# Pod jakými uživateli běží webserver a PHP?
ps -eo user,group,cmd | grep -E "[p]hp-fpm|[n]ginx|[a]pache2|[h]ttpd" | sort | uniq -c
# Údaje o účtu: domovský adresář a shell (uživatele upravte)
getent passwd www-data
# Má uživatel práva sudo?
sudo -l -U www-data
# Vlastní cronjoby?
sudo crontab -l -u www-data
# Klíče SSH v domovském adresáři (u Debianu/Ubuntu je to /var/www)
sudo ls -la /var/www/.ssh 2>/dev/null
```

Výsledky si poznamenejte pro každého uživatele poolu. Pokud všechny weby běží pod stejným uživatelem, je to první bod na seznamu; jak je oddělit, popisuje článek [Izolace poolů PHP-FPM pro každý web](https://phpsos.de/cs/blog/php-fpm-pools-isolieren/).

## Práva uživatele webserveru: co účet nepotřebuje

Následující přehled ukazuje, co uživatel webserveru typicky nepotřebuje a jak mu to odebrat.

| Právo | Proč je nebezpečné | Doporučení |
|---|---|---|
| Přihlašovací shell | Je možné přihlášení a interaktivní používání | Shell `/usr/sbin/nologin` |
| Záznamy sudo | Cesta k právům root | žádné záznamy, ani pro jednotlivé příkazy |
| Vlastní crontab | trvalá zadní vrátka, která přežijí každý restart | žádný, omezit pomocí `/etc/cron.allow` |
| Klíče SSH | Přihlášení zvenčí | žádné `authorized_keys` |
| Vlastnictví programového kódu | Kód lze měnit | Vlastníkem je uživatel pro nasazování |
| Práva zápisu mimo datové složky | Ukládání škodlivého kódu | jen uploady, cache, temp |
| Plná práva k databázi | Databáze jiných aplikací, přístup k souborům přes databázi | jen vlastní databáze, jen datová práva |

Shell nastavíte příkazem `usermod -s /usr/sbin/nologin www-data`. Pro cron platí: pokud existuje `/etc/cron.allow`, smějí zakládat vlastní cronjoby jen v něm uvedení uživatelé. Nově založené cronjoby nebo neznámé klíče SSH jsou typickým znamením, že se někdo v systému uchytil. Zvlášť výrazné varovné znamení popisuje článek [Varovné znamení: webserver spouští shell](https://phpsos.de/cs/blog/webserver-startet-shell/).

## Databáze: omezte práva na nezbytné

Databázový účet webu je fakticky druhým uživatelem webserveru. Jeho přístupové údaje leží v konfiguračním souboru aplikace a vložený kód je může přečíst. Proto by měl smět jen to, co aplikace v provozu potřebuje.

```sql
-- Příklad MySQL/MariaDB: vlastní účet pro každý web, jen datová práva
CREATE USER 'seite1'@'localhost' IDENTIFIED BY 'hier-ein-langes-Zufallspasswort';
GRANT SELECT, INSERT, UPDATE, DELETE ON seite1.* TO 'seite1'@'localhost';
-- Zkontrolovat práva
SHOW GRANTS FOR 'seite1'@'localhost';
```

Práva jako `FILE`, `SUPER` nebo `GRANT OPTION` a přístup k `*.*` aplikační účet nepotřebuje. Mnoho CMS potřebuje pro aktualizace navíc `CREATE`, `ALTER`, `INDEX` a `DROP`. Čistší je samostatný účet pro aktualizace a migrace, který se používá jen při údržbě. Požadavky ověřte v dokumentaci výrobce.

## PHP-FPM navíc omezit pomocí systemd

systemd může službu omezit v jejím pohledu na systém. Pro PHP-FPM se obzvlášť hodí některé volby z dokumentace systemd. Působí i na master proces, který startuje jako root.

```ini
# sudo systemctl edit php8.3-fpm
[Service]
# /usr, /boot a /etc jen pro čtení
ProtectSystem=full
# /home, /root a /run/user neviditelné
ProtectHome=true
# vlastní /tmp a /var/tmp jen pro tuto službu
PrivateTmp=true
# žádné rozšíření práv přes setuid nebo capabilities souborů
NoNewPrivileges=true
```

Tyto volby otestujte před nasazením do ostrého provozu. Pokud leží weby pod `/home`, `ProtectHome=true` přístup zablokuje. `NoNewPrivileges=true` může rušit programy, které PHP volá a které při startu mění svá skupinová práva, například některé lokální poštovní programy pro funkci PHP `mail()`. Postupujte proto po krocích:

1. Přidejte jednu volbu, restartujte službu, zkontrolujte `systemctl status php8.3-fpm`.
2. Otestujte klíčové funkce webu: přihlášení, formuláře, odesílání pošty, uploady, cronjoby aplikace.
3. Vyhodnoťte chybový log PHP-FPM a aplikace.
4. Teprve pak přidejte další volbu.

Nakonec socket: Podle příručky PHP dostává ve výchozím stavu práva `0660` pro uživatele a skupinu poolu. Nastavte `listen.owner` a `listen.group` tak, aby se mohl připojit jen webserver, ne každý lokální uživatel.

> **Tip:**
> Minimální práva jsou postoj, ne jednorázový projekt. Inventuru z tohoto článku opakujte po každé přestavbě a po každém novém webu, protože nové služby často přicházejí s velkorysými výchozími právy.

## Závěr: útočník zdědí to, co povolíte

Least Privilege zní jako teorie, ale je to velmi praktická otázka: co může udělat ten, kdo spouští kód jako uživatel webserveru? Na serveru se shellem, záznamem sudo, vlastním crontabem a databázovým účtem se všemi právy zní odpověď: téměř vše. Na omezeném serveru zůstane spíše u incidentu v jednom webu, který lze rozpoznat a vyčistit.

Změna nevyžaduje žádný nový software, jen pečlivou inventuru a postupné testy. Začněte body, které téměř nic nerozbijí, tedy shellem, sudo a klíči SSH, a poté postupujte k právům k databázi a volbám systemd.

## Jak konkrétně pomáhá PHP SOS?

- **Kontrola účtů:** Pro každý pool a webserver zaznamenáme uživatele, shell, záznamy sudo, cronjoby, klíče SSH a práva k databázi.
- **Snížení práv:** Odebereme, co není potřeba, a oddělíme účty pro nasazování, běh a údržbu.
- **Omezení služeb:** Ochranné volby systemd nastavujeme postupně a po každém kroku web testujeme.
- **Udržení v čase:** V rámci [hardeningu serveru](https://phpsos.de/cs/leistungen/server-haertung/) zdokumentujeme koncepci oprávnění pro budoucí změny.


## Časté dotazy

**Pod jakým uživatelem běží PHP na mém serveru?**  
Záleží na provozním režimu. U mod_php běží PHP jako uživatel Apache, například www-data nebo apache. U PHP-FPM určuje uživatele každý pool pomocí user a group; hlavní proces (master) většinou běží jako root, workery jako uživatel poolu. Příkaz ps to ukáže rychle.

**Potřebuje uživatel webserveru přihlašovací shell?**  
Ne. Nginx, Apache ani PHP-FPM nepotřebují pro tohoto uživatele interaktivní přihlášení. Shell jako /usr/sbin/nologin brání tomu, aby se někdo pod tímto účtem přihlásil. Nasazování probíhá pod samostatným uživatelem.

**Proč www-data nedávat žádná práva sudo, ani pro jediný příkaz?**  
Protože vložený kód zdědí přesně tato práva. I zdánlivě neškodný příkaz může být při chybném povolení cestou k právům root. Úlohy, které vyžadují vyšší oprávnění, patří do samostatných služeb nebo postupů mimo webserver.

**Pomůže to proti PHP2Shell?**  
Zranitelnost to neuzavře, k tomu je potřeba aktualizace PHP a restart všech workerů. Minimální práva ale omezují, co může útočník po úspěšném zneužití udělat: měnit soubory, uchytit se v systému, dosáhnout na jiné weby.

## Zdroje

- [Příručka PHP: konfigurace FPM (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/)
