Röviden: A webszerver-felhasználónak, amely alatt a PHP fut, a minimális jogok elve (Least Privilege) szerint csak azt szabad olvasnia, amire a weboldalnak szüksége van, és csak ott szabad írnia, ahol a weboldal adatokat tárol. Nincs bejelentkezési shellje, sudo-joga, saját cronjobja és SSH-kulcsa, adatbázis-fiókja pedig csak adatokat olvashat és módosíthat. A ProtectSystem és a PrivateTmp típusú systemd-opciók a PHP-FPM-et további korlátok közé szorítják.
A kérdés a betörés után: mit tehet ez a folyamat?
A PHP2Shell esetében a kártékony kód távoli, bejelentkezés nélküli végrehajtásáról van szó. Ha ez sikerül, a kód nem légüres térben fut, hanem egy meghatározott felhasználóként: a PHP-folyamat felhasználójaként. Mindent, amit ez a felhasználó megtehet, attól a pillanattól a támadó is megtehet.
Sok szerveren ez meglepően sok. A felhasználó birtokolja a teljes programkódot, van shellje, saját cronjobokat hozhat létre, az alkalmazás adatbázis-fiókjának pedig minden joga megvan az összes adatbázison. A támadó számára ez az ideális kiindulópont a tartós berendezkedéshez.
Hogyan osszon ki helyesen fájl- és mappajogokat, azt a Fájljogosultságok a webszerveren útmutató írja le. Ez a cikk magát a fiókot veszi górcső alá: a bejelentkezést, a különleges jogokat, az ütemezett feladatokat, az adatbázist és a határokat, amelyeket a systemd húz meg.
Leltár: ki a webszerver-felhasználó?
Először tisztázza, mely felhasználók érintettek egyáltalán. PHP-FPM esetén minden pool a user és a group beállítással határozza meg, kinek a nevében futnak a workerei. Mod_php esetén a PHP az Apache felhasználójaként fut. Hogyan működik együtt a mester és a worker a PHP-FPM-ben, azt a PHP-FPM magyarázata: folyamatkezelő, poolok és workerek írja le. A következő parancsok csak olvasnak:
# Mely felhasználók alatt futnak a webszerver és a PHP?
ps -eo user,group,cmd | grep -E "[p]hp-fpm|[n]ginx|[a]pache2|[h]ttpd" | sort | uniq -c
# Fiókadatok: saját könyvtár és shell (a felhasználót igazítsa)
getent passwd www-data
# Van sudo-joga a felhasználónak?
sudo -l -U www-data
# Saját cronjobok?
sudo crontab -l -u www-data
# SSH-kulcsok a saját könyvtárban (Debian/Ubuntu esetén ez a /var/www)
sudo ls -la /var/www/.ssh 2>/dev/null
Jegyezze fel az eredményeket minden pool-felhasználóra. Ha az összes weboldal ugyanazon felhasználó alatt fut, az a lista első pontja; hogyan választhatja szét őket, azt a PHP-FPM-poolok elkülönítése weboldalanként írja le.
A webszerver-felhasználó jogai: amire a fióknak nincs szüksége
A következő áttekintés megmutatja, mire nincs jellemzően szüksége egy webszerver-felhasználónak, és hogyan vonhatja meg tőle.
| Jog | Miért veszélyes | Ajánlás |
|---|---|---|
| Bejelentkezési shell | bejelentkezés és interaktív használat lehetséges | /usr/sbin/nologin shell |
| sudo-bejegyzések | út a root-jogokhoz | nincs bejegyzés, még egyes parancsokra sem |
| saját crontab | tartós hátsó ajtó, amely túléli az újraindításokat | nincs, a /etc/cron.allow fájllal korlátozni |
| SSH-kulcsok | kívülről történő bejelentkezés | nincs authorized_keys |
| a programkód birtoklása | a kód módosítható | a tulajdonos egy telepítési felhasználó |
| írásjog az adatmappákon kívül | kártékony kód lerakása | csak feltöltések, gyorsítótár, temp |
| teljes adatbázisjogok | más alkalmazások adatbázisai, fájlhozzáférés az adatbázison át | csak a saját adatbázis, csak adatjogok |
A shellt a usermod -s /usr/sbin/nologin www-data paranccsal állítja be. A cronra ez érvényes: ha létezik a /etc/cron.allow, csak az ott felsorolt felhasználók hozhatnak létre saját cronjobokat. Újonnan létrehozott cronjobok vagy ismeretlen SSH-kulcsok tipikus jelei annak, hogy valaki berendezkedett. Egy különösen egyértelmű figyelmeztető jelet ír le a Figyelmeztető jel: a webszerver shellt indít cikk.
Az adatbázis: a jogok korlátozása a szükségesre
Egy weboldal adatbázis-fiókja ténylegesen egy második webszerver-felhasználó. A hozzáférési adatai az alkalmazás konfigurációs fájljában vannak, és a beinjektált kód számára olvashatók. Ezért csak azt szabad tehetnie, amire az alkalmazásnak üzem közben szüksége van.
-- Példa MySQL/MariaDB: weboldalanként saját fiók, csak adatjogok
CREATE USER 'seite1'@'localhost' IDENTIFIED BY 'hier-ein-langes-Zufallspasswort';
GRANT SELECT, INSERT, UPDATE, DELETE ON seite1.* TO 'seite1'@'localhost';
-- Jogok ellenőrzése
SHOW GRANTS FOR 'seite1'@'localhost';
Az olyan jogokra, mint a FILE, a SUPER vagy a GRANT OPTION, és a *.* hozzáférésre egy alkalmazásfióknak nincs szüksége. Sok CMS a frissítésekhez ezenkívül CREATE, ALTER, INDEX és DROP jogot igényel. Tisztább megoldás a frissítésekhez és migrációkhoz használt külön fiók, amelyet csak a karbantartás idejére használ. Ellenőrizze a követelményeket a gyártó dokumentációjában.
A PHP-FPM további korlátozása systemd-vel
A systemd egy szolgáltatást korlátozhat abban, hogyan látja a rendszert. A PHP-FPM-hez a systemd-dokumentáció néhány opciója különösen alkalmas. Ezek a rootként induló mesterfolyamatra is hatnak.
# sudo systemctl edit php8.3-fpm
[Service]
# /usr, /boot és /etc csak olvasható
ProtectSystem=full
# /home, /root és /run/user láthatatlan
ProtectHome=true
# saját /tmp és /var/tmp csak ennek a szolgáltatásnak
PrivateTmp=true
# nincs jogosultság-bővítés setuid vagy fájl-capability útján
NoNewPrivileges=true
Éles használat előtt tesztelje ezeket az opciókat. Ha a weboldalak a /home alatt vannak, a ProtectHome=true megakadályozza a hozzáférést. A NoNewPrivileges=true zavarhatja azokat a programokat, amelyeket a PHP hív, és amelyek induláskor csoportjogot váltanak, például egyes helyi levelezőprogramokat a PHP mail() függvényéhez. Ezért lépésenként járjon el:
- Egy opciót hozzáadni, a szolgáltatást újraindítani, ellenőrizni a
systemctl status php8.3-fpmkimenetét. - A weboldal alapfunkcióit tesztelni: bejelentkezés, űrlapok, levélküldés, feltöltések, az alkalmazás cronjobjai.
- Kiértékelni a PHP-FPM és az alkalmazás hibanaplóját.
- Csak ezután hozzáadni a következő opciót.
Végül a socket: a PHP kézikönyve szerint alapértelmezés szerint 0660 jogokat kap a pool felhasználójának és csoportjának. A listen.owner és a listen.group értékét úgy állítsa be, hogy csak a webszerver csatlakozhasson, ne minden helyi felhasználó.
A minimális jogok alapállás, nem egyszeri projekt. A cikkben szereplő leltárat minden átalakítás és minden új weboldal után ellenőrizze újra, mert az új szolgáltatások gyakran nagyvonalú alapértelmezett jogokat hoznak magukkal.
Összegzés: a támadó azt örökli, amit Ön megenged
A Least Privilege elméletnek hangzik, valójában nagyon gyakorlati kérdés: mit tehet az, aki webszerver-felhasználóként hajt végre kódot? Egy olyan szerveren, ahol van shell, sudo-bejegyzés, saját crontab és minden joggal rendelkező adatbázis-fiók, a válasz: szinte bármit. Egy korlátozott szerveren inkább egyetlen weboldalon belüli incidens marad, amely felismerhető és megtisztítható.
Az átállás nem igényel új szoftvert, csak gondos leltárt és lépésenkénti teszteket. Kezdje azokkal a pontokkal, amelyek aligha tehetnek valamit tönkre, vagyis a shell, a sudo és az SSH-kulcsok, majd haladjon tovább az adatbázisjogok és a systemd-opciók felé.
Hogyan segít konkrétan a PHP SOS?
- Fiókok ellenőrzése: minden poolra és webszerverre felmérjük a felhasználót, a shellt, a sudo-bejegyzéseket, a cronjobokat, az SSH-kulcsokat és az adatbázisjogokat.
- Jogok csökkentése: megvonjuk, ami nem kell, és szétválasztjuk a telepítési, futási és karbantartási fiókokat.
- Szolgáltatások korlátozása: a systemd védelmi opcióit lépésenként állítjuk be, és minden lépés után teszteljük a weboldalt.
- Tartós fenntartás: a szerverkeményítés keretében dokumentáljuk a jogosultsági koncepciót a jövőbeli változtatásokhoz.
Gyakori kérdések
Melyik felhasználó alatt fut a PHP a szerveremen?
Ez az üzemmódtól függ. Mod_php esetén a PHP az Apache felhasználójaként fut, például www-data vagy apache néven. PHP-FPM esetén minden pool a user és a group beállítással határozza meg a saját felhasználóját; a mesterfolyamat általában rootként fut, a workerek a pool felhasználójaként. A ps parancs ezt gyorsan megmutatja.
Kell bejelentkezési shell a webszerver-felhasználónak?
Nem. Sem az Nginx, sem az Apache, sem a PHP-FPM nem igényel interaktív bejelentkezést ehhez a felhasználóhoz. Egy olyan shell, mint a /usr/sbin/nologin, megakadályozza, hogy bárki ezzel a fiókkal bejelentkezzen. A telepítések külön felhasználóval futnak.
Miért nincs sudo-jog a www-data számára, még egyetlen parancshoz sem?
Mert a beinjektált kód pontosan ezeket a jogokat örökli. Egy látszólag ártalmatlan parancs is root-jogokhoz vezethet, ha hibásan engedélyezték. A megemelt jogokat igénylő feladatok a webszerveren kívüli, különálló szolgáltatásokba vagy folyamatokba valók.
Segít ez a PHP2Shell ellen?
A rést nem zárja le, ahhoz a PHP-frissítés és az összes worker újraindítása kell. A minimális jogok viszont korlátozzák, mit tehet a támadó egy sikeres kihasználás után: módosíthat fájlokat, berendezkedhet, elérhet más weboldalakat.