Kort sagt: Webbserveranvändaren som PHP körs under bör enligt principen om minimala rättigheter (Least Privilege) bara läsa det webbplatsen behöver och bara skriva där den lagrar data. Den har inget inloggningsskal, inga sudo-rättigheter, inga egna cronjobb och inga SSH-nycklar, och dess databaskonto får bara läsa och ändra data. systemd-alternativ som ProtectSystem och PrivateTmp avgränsar dessutom PHP-FPM.
Frågan efter intrånget: vad får den här processen göra?
PHP2Shell handlar om att köra skadlig kod på distans utan inloggning. Lyckas det körs koden inte i ett vakuum utan som en alldeles bestämd användare: PHP-processens användare. Allt den användaren får göra får från och med det ögonblicket även angriparen göra.
På många servrar är det förvånansvärt mycket. Användaren äger hela programkoden, har ett skal, kan skapa egna cronjobb, och applikationens databaskonto har alla rättigheter på alla databaser. För en angripare är det det perfekta utgångsläget för att etablera sig varaktigt.
Hur ni sätter filer och mappar rätt beskriver guiden Filrättigheter på webbservern. Det här inlägget tittar på själva kontot: inloggning, specialrättigheter, schemalagda uppgifter, databas och de gränser som systemd drar.
Inventering: vem är webbserveranvändaren?
Först klargör ni vilka användare som över huvud taget är inblandade. Med PHP-FPM bestämmer varje pool med user och group under vem dess workers körs. Med mod_php körs PHP som Apache-användare. Hur huvudprocess och workers samverkar i PHP-FPM förklarar PHP-FPM förklarat: processhanterare, pooler och workers. Följande kommandon läser bara:
# Under vilka användare körs webbserver och PHP?
ps -eo user,group,cmd | grep -E "[p]hp-fpm|[n]ginx|[a]pache2|[h]ttpd" | sort | uniq -c
# Kontouppgifter: hemkatalog och skal (anpassa användaren)
getent passwd www-data
# Har användaren sudo-rättigheter?
sudo -l -U www-data
# Egna cronjobb?
sudo crontab -l -u www-data
# SSH-nycklar i hemkatalogen (på Debian/Ubuntu är det /var/www)
sudo ls -la /var/www/.ssh 2>/dev/null
Anteckna resultaten för varje poolanvändare. Körs alla webbplatser under samma användare är det första punkten på listan; hur ni delar upp det beskriver Isolera PHP-FPM-pooler per webbplats.
Webbserveranvändarens behörigheter: vad kontot inte behöver
Följande översikt visar vad en webbserveranvändare typiskt inte behöver och hur ni drar in det.
| Behörighet | Varför farligt | Rekommendation |
|---|---|---|
| Inloggningsskal | Inloggning och interaktiv användning möjlig | Skal /usr/sbin/nologin |
| sudo-poster | Väg till root-rättigheter | inga poster, inte ens för enstaka kommandon |
| egen crontab | varaktig bakdörr som överlever varje omstart | ingen, begränsa via /etc/cron.allow |
| SSH-nycklar | Inloggning utifrån | inga authorized_keys |
| Äganderätt till programkoden | Koden kan ändras | Ägare är en driftsättningsanvändare |
| Skrivrättigheter utanför datamappar | Utplacering av skadlig kod | bara uppladdningar, cache, temp |
| fulla databasrättigheter | Andra applikationers databaser, filåtkomst via databasen | bara den egna databasen, bara datarättigheter |
Skalet sätter ni med usermod -s /usr/sbin/nologin www-data. För cron gäller: Finns /etc/cron.allow får bara de användare som nämns där skapa egna cronjobb. Nyskapade cronjobb eller okända SSH-nycklar är ett typiskt tecken på att någon har etablerat sig. En särskilt tydlig varningssignal beskriver inlägget Varningssignal: webbservern startar ett skal.
Databasen: begränsa rättigheterna till det nödvändiga
En webbplats databaskonto är i praktiken en andra webbserveranvändare. Inloggningsuppgifterna ligger i applikationens konfigurationsfil och är läsbara för inplanterad kod. Därför bör kontot bara få göra det applikationen behöver i drift.
-- Exempel MySQL/MariaDB: eget konto per webbplats, bara datarättigheter
CREATE USER 'seite1'@'localhost' IDENTIFIED BY 'hier-ein-langes-Zufallspasswort';
GRANT SELECT, INSERT, UPDATE, DELETE ON seite1.* TO 'seite1'@'localhost';
-- Kontrollera rättigheterna
SHOW GRANTS FOR 'seite1'@'localhost';
Rättigheter som FILE, SUPER eller GRANT OPTION och åtkomst till *.* behöver ett applikationskonto inte. Många CMS behöver för uppdateringar dessutom CREATE, ALTER, INDEX och DROP. Renare är ett separat konto för uppdateringar och migreringar som bara används under underhåll. Kontrollera kraven i tillverkarens dokumentation.
Avgränsa PHP-FPM ytterligare med systemd
systemd kan begränsa en tjänsts syn på systemet. För PHP-FPM lämpar sig några alternativ ur systemd-dokumentationen särskilt väl. De verkar även på huvudprocessen, som startar som root.
# sudo systemctl edit php8.3-fpm
[Service]
# /usr, /boot och /etc skrivskyddade
ProtectSystem=full
# /home, /root och /run/user osynliga
ProtectHome=true
# eget /tmp och /var/tmp bara för den här tjänsten
PrivateTmp=true
# ingen rättighetsutökning via setuid eller fil-capabilities
NoNewPrivileges=true
Testa alternativen före produktiv användning. Ligger webbplatser under /home förhindrar ProtectHome=true åtkomsten. NoNewPrivileges=true kan störa program som PHP anropar och som byter grupprättigheter vid start, till exempel vissa lokala e-postprogram för PHP-funktionen mail(). Gå därför fram i steg:
- Lägg till ett alternativ, starta om tjänsten, kontrollera
systemctl status php8.3-fpm. - Testa webbplatsens kärnfunktioner: inloggning, formulär, e-postutskick, uppladdningar, applikationens cronjobb.
- Gå igenom felloggen för PHP-FPM och applikationen.
- Först därefter lägger ni till nästa alternativ.
Till sist socketen: Enligt PHP-manualen får den som standard rättigheterna 0660 för poolens användare och grupp. Sätt listen.owner och listen.group så att bara webbservern kan ansluta, inte varje lokal användare.
Minimala rättigheter är ett förhållningssätt, inte ett engångsprojekt. Upprepa inventeringen från det här inlägget efter varje ombyggnad och varje ny webbplats, för nya tjänster har ofta generösa standardrättigheter med sig.
Slutsats: angriparen ärver det ni tillåter
Least Privilege låter som teori men är en mycket praktisk fråga: vad kan den som kör kod som webbserveranvändare göra? På en server med skal, sudo-post, egen crontab och ett databaskonto med alla rättigheter lyder svaret: nästan allt. På en avgränsad server stannar det oftare vid en incident i en enskild webbplats, som går att upptäcka och rensa.
Omställningen kräver ingen ny programvara, bara en noggrann inventering och stegvisa tester. Börja med de punkter som knappast kan förstöra något, alltså skal, sudo och SSH-nycklar, och arbeta er sedan vidare till databasrättigheter och systemd-alternativ.
Hur hjälper PHP SOS konkret?
- Kontrollera konton: Vi går igenom användare, skal, sudo-poster, cronjobb, SSH-nycklar och databasrättigheter för varje pool och webbserver.
- Minska rättigheter: Vi drar in det som inte behövs och skiljer driftsättnings-, drift- och underhållskonton åt.
- Avgränsa tjänster: Vi sätter systemd-skyddsalternativ stegvis och testar webbplatsen efter varje steg.
- Hålla det över tid: Inom ramen för serverhärdning dokumenterar vi behörighetskonceptet för framtida ändringar.
Vanliga frågor
Under vilken användare körs PHP på min server?
Det beror på driftläget. Med mod_php körs PHP som Apache-användare, till exempel www-data eller apache. Med PHP-FPM bestämmer varje pool sin användare med user och group; huvudprocessen körs oftast som root, workers som poolens användare. Kommandot ps visar det snabbt.
Behöver webbserveranvändaren ett inloggningsskal?
Nej. Varken Nginx, Apache eller PHP-FPM behöver en interaktiv inloggning för den här användaren. Ett skal som /usr/sbin/nologin hindrar att någon loggar in med kontot. Driftsättningar går via en egen användare.
Varför inga sudo-rättigheter för www-data, inte ens för ett enda kommando?
Därför att inplanterad kod ärver precis de rättigheterna. Redan ett till synes ofarligt kommando kan, om det frigörs fel, leda till root-rättigheter. Uppgifter som kräver utökade rättigheter hör hemma i separata tjänster eller rutiner utanför webbservern.
Hjälper det mot PHP2Shell?
Det stänger inte sårbarheten, för det krävs PHP-uppdateringen och omstart av alla workers. Minimala rättigheter begränsar dock vad en angripare kan göra efter ett lyckat utnyttjande: ändra filer, etablera sig, nå andra webbplatser.