Lyhyesti: Verkkopalvelinkäyttäjän, jonka alla PHP toimii, tulisi vähimmän oikeuden periaatteen (Least Privilege) mukaisesti vain lukea sen, mitä verkkosivusto tarvitsee, ja kirjoittaa vain siihen, minne se tallentaa tietoja. Sillä ei ole kirjautumisshelliä, sudo-oikeuksia, omia cron-tehtäviä eikä SSH-avaimia, ja sen tietokantatili saa vain lukea ja muuttaa tietoja. systemd-asetukset kuten ProtectSystem ja PrivateTmp rajaavat PHP-FPM:ää lisäksi.
Kysymys tunkeutumisen jälkeen: mitä tämä prosessi saa tehdä?
PHP2Shellissä on kyse haittakoodin suorittamisesta etänä ilman kirjautumista. Jos hyökkäys onnistuu, koodi ei toimi tyhjiössä vaan tietyn käyttäjän alla: PHP-prosessin käyttäjänä. Kaiken, minkä tämä käyttäjä saa tehdä, saa tästä hetkestä alkaen tehdä myös hyökkääjä.
Monella palvelimella se on yllättävän paljon. Käyttäjä omistaa koko ohjelmakoodin, sillä on shell, se voi luoda omia cron-tehtäviä, ja sovelluksen tietokantatilillä on kaikki oikeudet kaikkiin tietokantoihin. Hyökkääjälle tämä on ihanteellinen lähtökohta asettua pysyvästi.
Miten tiedostot ja kansiot määritetään oikein, kuvaa opas Tiedosto-oikeudet verkkopalvelimella. Tämä kirjoitus keskittyy itse tiliin: kirjautumiseen, erityisoikeuksiin, ajastettuihin tehtäviin, tietokantaan ja rajoihin, jotka systemd asettaa.
Kartoitus: kuka on verkkopalvelinkäyttäjä?
Selvittäkää ensin, mitkä käyttäjät ovat ylipäätään mukana. PHP-FPM:ssä jokainen pooli määrää asetuksilla user ja group, minkä käyttäjän alla sen workerit toimivat. mod_php:ssa PHP toimii Apache-käyttäjänä. Miten pääprosessi ja workerit toimivat yhdessä PHP-FPM:ssä, selittää PHP-FPM selitettynä: prosessinhallinta, poolit ja workerit. Seuraavat komennot vain lukevat:
# Minkä käyttäjien alla verkkopalvelin ja PHP toimivat?
ps -eo user,group,cmd | grep -E "[p]hp-fpm|[n]ginx|[a]pache2|[h]ttpd" | sort | uniq -c
# Tilin tiedot: kotihakemisto ja shell (mukauta käyttäjä)
getent passwd www-data
# Onko käyttäjällä sudo-oikeuksia?
sudo -l -U www-data
# Omia cron-tehtäviä?
sudo crontab -l -u www-data
# SSH-avaimet kotihakemistossa (Debianissa/Ubuntussa se on /var/www)
sudo ls -la /var/www/.ssh 2>/dev/null
Kirjatkaa tulokset jokaiselle pooli-käyttäjälle. Jos kaikki verkkosivustot toimivat saman käyttäjän alla, se on listan ensimmäinen kohta; miten ne erotetaan, kuvaa PHP-FPM-poolien eristäminen sivustokohtaisesti.
Verkkopalvelinkäyttäjän oikeudet: mitä tili ei tarvitse
Seuraava yleiskatsaus näyttää, mitä verkkopalvelinkäyttäjä tyypillisesti ei tarvitse ja miten se poistetaan.
| Oikeus | Miksi vaarallinen | Suositus |
|---|---|---|
| Kirjautumisshell | kirjautuminen ja interaktiivinen käyttö mahdollista | shell /usr/sbin/nologin |
| sudo-merkinnät | tie root-oikeuksiin | ei merkintöjä, ei edes yksittäisille komennoille |
| oma crontab | pysyvä takaovi, joka säilyy jokaisen uudelleenkäynnistyksen yli | ei lainkaan, rajaus tiedostolla /etc/cron.allow |
| SSH-avaimet | kirjautuminen ulkopuolelta | ei authorized_keys-tiedostoa |
| ohjelmakoodin omistus | koodia voidaan muuttaa | omistajana on käyttöönottokäyttäjä |
| kirjoitusoikeudet datakansioiden ulkopuolelle | haittakoodin tallennus | vain uploadit, välimuisti, temp |
| täydet tietokantaoikeudet | muiden sovellusten tietokannat, tiedostoihin pääsy tietokannan kautta | vain oma tietokanta, vain dataoikeudet |
Shellin asetatte komennolla usermod -s /usr/sbin/nologin www-data. Cronin osalta pätee: jos /etc/cron.allow on olemassa, vain siinä mainitut käyttäjät saavat luoda omia cron-tehtäviä. Uudet cron-tehtävät tai tuntemattomat SSH-avaimet ovat tyypillinen merkki siitä, että joku on asettunut palvelimelle. Erityisen selvän varoitusmerkin kuvaa kirjoitus Varoitusmerkki: verkkopalvelin käynnistää shellin.
Tietokanta: oikeudet vain välttämättömään
Verkkosivuston tietokantatili on käytännössä toinen verkkopalvelinkäyttäjä. Sen tunnukset ovat sovelluksen asetustiedostossa, ja ujutettu koodi voi lukea ne. Siksi tilin tulisi saada tehdä vain se, mitä sovellus tarvitsee käytön aikana.
-- Esimerkki MySQL/MariaDB: oma tili jokaiselle sivustolle, vain dataoikeudet
CREATE USER 'seite1'@'localhost' IDENTIFIED BY 'hier-ein-langes-Zufallspasswort';
GRANT SELECT, INSERT, UPDATE, DELETE ON seite1.* TO 'seite1'@'localhost';
-- Tarkista oikeudet
SHOW GRANTS FOR 'seite1'@'localhost';
Oikeuksia kuten FILE, SUPER tai GRANT OPTION ja pääsyä kohteeseen *.* sovellustili ei tarvitse. Monet CMS-järjestelmät tarvitsevat päivityksiin lisäksi oikeudet CREATE, ALTER, INDEX ja DROP. Siistimpää on erillinen tili päivityksiä ja migraatioita varten, jota käytetään vain huoltokatkon aikana. Tarkistakaa vaatimukset valmistajan dokumentaatiosta.
PHP-FPM:n rajaaminen lisäksi systemd:llä
systemd voi rajoittaa palvelun näkymää järjestelmään. PHP-FPM:lle sopivat erityisen hyvin muutamat systemd-dokumentaation asetukset. Ne vaikuttavat myös pääprosessiin, joka käynnistyy rootina.
# sudo systemctl edit php8.3-fpm
[Service]
# /usr, /boot ja /etc vain luku -tilassa
ProtectSystem=full
# /home, /root ja /run/user näkymättömiksi
ProtectHome=true
# oma /tmp ja /var/tmp vain tälle palvelulle
PrivateTmp=true
# ei oikeuksien laajennusta setuid:n tai tiedosto-capabilityjen kautta
NoNewPrivileges=true
Testatkaa nämä asetukset ennen tuotantokäyttöä. Jos verkkosivustot sijaitsevat hakemistossa /home, ProtectHome=true estää pääsyn. NoNewPrivileges=true voi häiritä ohjelmia, joita PHP kutsuu ja jotka vaihtavat ryhmäoikeuksiaan käynnistyessään, esimerkiksi joitakin paikallisia sähköpostiohjelmia PHP-funktiota mail() varten. Edetkää siksi vaiheittain:
- Lisätkää yksi asetus, käynnistäkää palvelu uudelleen ja tarkistakaa
systemctl status php8.3-fpm. - Testatkaa verkkosivuston keskeiset toiminnot: kirjautuminen, lomakkeet, sähköpostin lähetys, uploadit, sovelluksen cron-tehtävät.
- Käykää läpi PHP-FPM:n ja sovelluksen virheloki.
- Vasta sitten lisätkää seuraava asetus.
Lopuksi socket: PHP-käsikirjan mukaan sen oletusoikeudet ovat 0660 poolin käyttäjälle ja ryhmälle. Asettakaa listen.owner ja listen.group niin, että vain verkkopalvelin voi muodostaa yhteyden, ei jokainen paikallinen käyttäjä.
Vähimmät oikeudet ovat asenne, eivät kertaluonteinen projekti. Toistakaa tämän kirjoituksen kartoitus jokaisen muutoksen ja jokaisen uuden verkkosivuston jälkeen, sillä uudet palvelut tuovat usein mukanaan liian väljät oletusoikeudet.
Yhteenveto: hyökkääjä perii sen, minkä sallitte
Vähimmän oikeuden periaate kuulostaa teorialta, mutta on hyvin käytännöllinen kysymys: mitä voi tehdä joku, joka suorittaa koodia verkkopalvelinkäyttäjänä? Palvelimella, jolla on shell, sudo-merkintä, oma crontab ja tietokantatili kaikilla oikeuksilla, vastaus on: lähes mitä tahansa. Rajatulla palvelimella tilanne jää todennäköisemmin yksittäisen verkkosivuston tapaukseksi, joka voidaan tunnistaa ja puhdistaa.
Muutos ei vaadi uutta ohjelmistoa, vain huolellisen kartoituksen ja vaiheittaisia testejä. Aloittakaa kohdista, jotka eivät juuri voi rikkoa mitään eli shellistä, sudosta ja SSH-avaimista, ja siirtykää sitten tietokantaoikeuksiin ja systemd-asetuksiin.
Miten PHP SOS auttaa konkreettisesti?
- Tilien tarkistus: Kartoitamme jokaisen poolin ja verkkopalvelimen käyttäjän, shellin, sudo-merkinnät, cron-tehtävät, SSH-avaimet ja tietokantaoikeudet.
- Oikeuksien vähentäminen: Poistamme sen, mitä ei tarvita, ja erotamme käyttöönotto-, ajo- ja huoltotilit toisistaan.
- Palvelujen rajaaminen: Asetamme systemd-suojausasetukset vaiheittain ja testaamme verkkosivuston jokaisen vaiheen jälkeen.
- Pysyvä ylläpito: Dokumentoimme palvelimen koventamisen yhteydessä oikeuskonseptin tulevia muutoksia varten.
Usein kysytyt kysymykset
Minkä käyttäjän alla PHP toimii palvelimellani?
Se riippuu käyttötavasta. mod_php:ssa PHP toimii Apache-käyttäjänä, esimerkiksi www-data tai apache. PHP-FPM:ssä jokainen pooli määrittää käyttäjänsä asetuksilla user ja group; pääprosessi toimii yleensä rootina ja workerit pooli-käyttäjänä. Komento ps näyttää tämän nopeasti.
Tarvitseeko verkkopalvelinkäyttäjä kirjautumisshellin?
Ei. Nginx, Apache tai PHP-FPM eivät tarvitse tälle käyttäjälle interaktiivista kirjautumista. Shell kuten /usr/sbin/nologin estää kirjautumisen tällä tilillä. Käyttöönotot tehdään erillisellä käyttäjällä.
Miksi www-datalle ei anneta sudo-oikeuksia, ei edes yhteen komentoon?
Koska ujutettu koodi perii juuri nämä oikeudet. Jo näennäisen harmiton komento voi väärin sallittuna johtaa root-oikeuksiin. Tehtävät, jotka vaativat korotettuja oikeuksia, kuuluvat erillisiin palveluihin tai työnkulkuihin verkkopalvelimen ulkopuolella.
Auttaako tämä PHP2Shelliä vastaan?
Se ei sulje aukkoa; siihen tarvitaan PHP-päivitys ja kaikkien workerien uudelleenkäynnistys. Vähimmät oikeudet rajoittavat kuitenkin sitä, mitä hyökkääjä voi onnistuneen hyväksikäytön jälkeen tehdä: muuttaa tiedostoja, asettua pysyvästi tai päästä muille verkkosivustoille.