Na kratko: Uporabnik spletnega strežnika, pod katerim teče PHP, naj po načelu minimalnih pravic (Least Privilege) bere samo tisto, kar spletna stran potrebuje, in piše samo tja, kjer shranjuje podatke. Nima prijavne lupine, pravic sudo, lastnih opravil cron ne ključev SSH, njegov račun za bazo podatkov pa sme podatke samo brati in spreminjati. Možnosti systemd, kot sta ProtectSystem in PrivateTmp, PHP-FPM dodatno omejijo.
Vprašanje po vdoru: kaj sme ta proces?
Pri PHP2Shell gre za izvajanje škodljive kode na daljavo brez prijave. Če uspe, koda ne teče v praznem prostoru, ampak kot povsem določen uporabnik: uporabnik procesa PHP. Vse, kar ta uporabnik sme, od tistega trenutka sme tudi napadalec.
Na mnogih strežnikih je to presenetljivo veliko. Uporabnik je lastnik vse programske kode, ima lupino, lahko ustvarja lastna opravila cron, račun aplikacije za bazo podatkov pa ima vse pravice za vse baze. Za napadalca je to idealno izhodišče za trajno utrditev v sistemu.
Kako pravilno dodelite datoteke in mape, opisuje vodnik Pravice datotek na spletnem strežniku. Ta prispevek obravnava sam račun: prijavo, posebne pravice, načrtovana opravila, bazo podatkov in meje, ki jih postavi systemd.
Popis: kdo je uporabnik spletnega strežnika?
Najprej ugotovite, kateri uporabniki sploh sodelujejo. Pri PHP-FPM vsak pool z user in group določi, pod kom tečejo njegovi workerji. Pri mod_php teče PHP kot uporabnik Apacheja. Kako glavni proces in workerji sodelujejo pri PHP-FPM, pojasnjuje PHP-FPM pojasnjen: upravitelj procesov, pooli in workerji. Naslednji ukazi samo berejo:
# Pod katerimi uporabniki tečeta spletni strežnik in PHP?
ps -eo user,group,cmd | grep -E "[p]hp-fpm|[n]ginx|[a]pache2|[h]ttpd" | sort | uniq -c
# Podatki o računu: domači imenik in lupina (prilagodite uporabnika)
getent passwd www-data
# Ima uporabnik pravice sudo?
sudo -l -U www-data
# Lastna opravila cron?
sudo crontab -l -u www-data
# Ključi SSH v domačem imeniku (pri Debianu/Ubuntuju je to /var/www)
sudo ls -la /var/www/.ssh 2>/dev/null
Rezultate zabeležite za vsakega uporabnika poola. Če vse spletne strani tečejo pod istim uporabnikom, je to prva točka na seznamu; kako to ločite, opisuje Izolacija poolov PHP-FPM po spletnih straneh.
Pravice uporabnika spletnega strežnika: česa račun ne potrebuje
Spodnji pregled prikazuje, česa uporabnik spletnega strežnika običajno ne potrebuje in kako mu to odvzamete.
| Pravica | Zakaj je nevarna | Priporočilo |
|---|---|---|
| Prijavna lupina | možna prijava in interaktivna uporaba | lupina /usr/sbin/nologin |
| Vnosi sudo | pot do pravic root | brez vnosov, tudi za posamezne ukaze ne |
| Lastna datoteka crontab | trajna stranska vrata, ki preživijo vsak ponovni zagon | brez nje, omejitev z /etc/cron.allow |
| Ključi SSH | prijava od zunaj | brez authorized_keys |
| Lastništvo programske kode | kodo je mogoče spreminjati | lastnik je uporabnik za razmestitev (deploy) |
| Pravice pisanja zunaj podatkovnih map | shranjevanje škodljive kode | samo uploads, cache, temp |
| Polne pravice baze podatkov | baze drugih aplikacij, dostop do datotek prek baze | samo lastna baza, samo podatkovne pravice |
Lupino nastavite z usermod -s /usr/sbin/nologin www-data. Za cron velja: če obstaja /etc/cron.allow, smejo lastna opravila cron ustvarjati samo tam navedeni uporabniki. Na novo ustvarjena opravila cron ali neznani ključi SSH so tipičen znak, da se je nekdo utrdil v sistemu. Posebej jasen opozorilni znak opisuje prispevek Opozorilni znak: spletni strežnik zažene lupino.
Baza podatkov: pravice omejite na nujno
Račun spletne strani za bazo podatkov je dejansko drugi uporabnik spletnega strežnika. Njegovi dostopni podatki so v konfiguracijski datoteki aplikacije in so za vneseno kodo berljivi. Zato naj sme samo tisto, kar aplikacija potrebuje med delovanjem.
-- Primer MySQL/MariaDB: lasten račun za vsako spletno stran, samo podatkovne pravice
CREATE USER 'seite1'@'localhost' IDENTIFIED BY 'hier-ein-langes-Zufallspasswort';
GRANT SELECT, INSERT, UPDATE, DELETE ON seite1.* TO 'seite1'@'localhost';
-- Preverjanje pravic
SHOW GRANTS FOR 'seite1'@'localhost';
Pravic, kot so FILE, SUPER ali GRANT OPTION, ter dostopa do *.* račun aplikacije ne potrebuje. Mnogi CMS-ji za posodobitve dodatno potrebujejo CREATE, ALTER, INDEX in DROP. Čistejši je ločen račun za posodobitve in migracije, ki se uporablja samo med vzdrževanjem. Zahteve preverite v dokumentaciji proizvajalca.
PHP-FPM dodatno omejite s systemd
systemd lahko storitvi omeji pogled na sistem. Za PHP-FPM so posebej primerne nekatere možnosti iz dokumentacije systemd. Delujejo tudi na glavni proces, ki se zažene kot root.
# sudo systemctl edit php8.3-fpm
[Service]
# /usr, /boot in /etc samo za branje
ProtectSystem=full
# /home, /root in /run/user nevidni
ProtectHome=true
# lasten /tmp in /var/tmp samo za to storitev
PrivateTmp=true
# brez razširitve pravic prek setuid ali zmožnosti datotek (capabilities)
NoNewPrivileges=true
Te možnosti preizkusite pred produkcijsko uporabo. Če so spletne strani pod /home, ProtectHome=true prepreči dostop. NoNewPrivileges=true lahko moti programe, ki jih PHP kliče in ki ob zagonu zamenjajo skupinske pravice, na primer nekatere lokalne poštne programe za funkcijo PHP mail(). Zato ukrepajte po korakih:
- Dodajte eno možnost, znova zaženite storitev, preverite
systemctl status php8.3-fpm. - Preizkusite ključne funkcije spletne strani: prijavo, obrazce, pošiljanje e-pošte, nalaganje datotek, opravila cron aplikacije.
- Ocenite dnevnik napak PHP-FPM in aplikacije.
- Šele nato dodajte naslednjo možnost.
Na koncu še vtičnica (socket): po priročniku PHP privzeto dobi pravice 0660 za uporabnika in skupino poola. listen.owner in listen.group nastavite tako, da se lahko poveže samo spletni strežnik, ne vsak lokalni uporabnik.
Minimalne pravice so osnovna drža, ne enkraten projekt. Popis iz tega prispevka po vsaki prenovi in po vsaki novi spletni strani ponovite, saj nove storitve pogosto prinesejo radodarne privzete pravice.
Sklep: napadalec podeduje, kar dovolite
Least Privilege zveni teoretično, a je zelo praktično vprašanje: kaj lahko stori nekdo, ki izvaja kodo kot uporabnik spletnega strežnika? Na strežniku z lupino, vnosom sudo, lastno datoteko crontab in računom za bazo z vsemi pravicami je odgovor: skoraj vse. Na omejenem strežniku ostane incident prej v eni sami spletni strani, ki jo je mogoče prepoznati in očistiti.
Prehod ne zahteva nove programske opreme, samo skrben popis in postopno testiranje. Začnite s točkami, ki skoraj ničesar ne morejo pokvariti, torej z lupino, sudo in ključi SSH, nato pa nadaljujte s pravicami baze podatkov in možnostmi systemd.
Kako konkretno pomaga PHP SOS?
- Preverjanje računov: Za vsak pool in uporabnika spletnega strežnika zajamemo uporabnika, lupino, vnose sudo, opravila cron, ključe SSH in pravice baze podatkov.
- Zmanjšanje pravic: Odvzamemo, česar ni treba, in ločimo račune za razmestitev, izvajanje in vzdrževanje.
- Omejitev storitev: Zaščitne možnosti systemd nastavljamo postopno in po vsakem koraku preizkusimo spletno stran.
- Trajno vzdrževanje: V okviru utrjevanja strežnika dokumentiramo zasnovo pravic za prihodnje spremembe.
Pogosta vprašanja
Pod katerim uporabnikom teče PHP na mojem strežniku?
To je odvisno od načina delovanja. Pri mod_php teče PHP kot uporabnik Apacheja, na primer www-data ali apache. Pri PHP-FPM vsak pool z user in group določi svojega uporabnika; glavni proces večinoma teče kot root, workerji pa kot uporabnik poola. Ukaz ps to hitro pokaže.
Ali uporabnik spletnega strežnika potrebuje prijavno lupino?
Ne. Niti Nginx niti Apache niti PHP-FPM za tega uporabnika ne potrebujejo interaktivne prijave. Lupina, kot je /usr/sbin/nologin, prepreči, da bi se kdo prijavil s tem računom. Namestitve potekajo prek lastnega uporabnika.
Zakaj www-data ne dobi pravic sudo, niti za en sam ukaz?
Ker vnesena koda podeduje natanko te pravice. Že na videz neškodljiv ukaz lahko, če je napačno odobren, vodi do pravic root. Naloge, ki potrebujejo višje pravice, sodijo v ločene storitve ali postopke zunaj spletnega strežnika.
Ali to pomaga proti PHP2Shell?
Ranljivosti ne zapre, za to sta potrebna posodobitev PHP in ponovni zagon vseh workerjev. Minimalne pravice pa omejijo, kaj lahko napadalec stori po uspešnem izkoriščanju: spreminjanje datotek, utrditev v sistemu, dostop do drugih spletnih strani.