Ajankohtainen tilanne: PHP2Shell. Kaksi kriittistä PHP-haavoittuvuutta (CVSS 9.2) sallii haittakoodin suorittamisen ilman kirjautumista. Korjaukset 21.10.2026 alkaen.Mitä nyt on tehtävä →

PHP-FPM-poolien eristys sivustoittain

Oma pooli jokaiselle sivustolle on alku, ei loppu. Näin tarkistatte nykyiset poolit ja koventatte socketit, päätteet, tilasivut, resurssit ja lokit.

Tilanne Lukuaika 4 minKoventaminen ja asetukset

Lyhyesti: Jokaisella palvelimen verkkosivustolla pitäisi olla oma PHP-FPM-pooli, oma järjestelmäkäyttäjä ja oma socket. Eristys tulee tehokkaaksi vasta yksityiskohdilla: socketin oikeudet vain verkkopalvelimelle, security.limit_extensions arvoon .php, ei julkisesti saavutettavia tilasivuja, omat rajat prosesseille ja suoritusajalle sekä erilliset lokit. PHP2Shelliltä suojaa vain päivitys; poolit rajaavat, kuinka pitkälle hyökkäys ulottuu.

Yksi palvelin, monta sivustoa, yhteinen riski

Monella palvelimella on vuosien mittaan kasvanut sellaista, mitä kukaan ei ole niin suunnitellut. Yrityksen verkkosivusto, verkkokauppa, vuoden 2019 kampanjasivu ja testijärjestelmä pyörivät rinnakkain, usein saman käyttäjän alla ja samassa poolissa. Jos unohdettu kampanjasivu vaarantuu, myös verkkokaupan asiakastiedot ovat vaarassa.

PHP-FPM, PHP:n FastCGI-prosessinhallinta, ratkaisee tämän pooleilla: workeriprosessien ryhmillä, joilla on omat asetukset. Perusperiaatteen selittää PHP-FPM selitettynä: prosessinhallinta, poolit ja workerit. Erillisten poolien rakentamisen omalla käyttäjällä, omalla väliaikaiskansiolla ja open_basedir-asetuksella kuvaa opas open_basedir ja eristys sivustoittain. Tämä kirjoitus menee askeleen pidemmälle: miten nykyiset poolit tarkistetaan, ja mitkä asetukset tekevät erottelusta kestävän?

Tärkeä huomio: PHP2Shellin aukot CVE-2026-109618 ja CVE-2026-109619 ovat PHP-tulkissa, jonka kaikki saman PHP-version poolit jakavat. Oma pooli ei estä hyväksikäyttöä. Se ratkaisee kuitenkin, saavuttaako hyökkääjä sen jälkeen yhden vai kaikki sivustot.

PHP-FPM-poolit omalla käyttäjällä: nykytilan tarkistus

Ennen kuin muutatte mitään, hankkikaa yleiskuva. Seuraavat komennot vain lukevat. Polut ja versionumerot vaihtelevat jakelun mukaan:

# Kaikki poolit käyttäjineen ja socketteineen
grep -HE '^\s*(\[|user|group|listen)\s*' /etc/php/*/fpm/pool.d/*.conf

# Käynnissä olevat poolit ja niiden käyttäjät
ps -eo user,pid,cmd | grep '[p]hp-fpm: pool'

# Socketit ja niiden oikeudet
ls -l /run/php/

# Tarkista asetukset virheiden varalta (ei muuta mitään)
sudo php-fpm8.3 -t

Kiinnittäkää huomiota kolmeen kuvioon: useita sivustoja samassa poolissa, poolit, jotka pyörivät käyttäjänä www-data tai jopa root, ja socketit, joihin kaikilla käyttäjillä on kirjoitusoikeus. Jokainen niistä heikentää erottelua.

Jos palvelimella pyörii useita PHP-versioita, jokaisella on oma FPM-palvelunsa ja omat pool-hakemistonsa. Tarkistakaa ne kaikki, älkää vain versiota, jonka otitte viimeksi käyttöön. Juuri vanhat versiot unohdetuine pooleineen ovat riski, koska niitä ei usein ylläpidetä eikä käynnistetä päivitysten jälkeen uudelleen. Vinkkejä löytyy kohdasta Useita PHP-versioita samalla palvelimella. Kirjatkaa tulos pieneen taulukkoon: sivusto, pooli, käyttäjä, socket, PHP-versio. Tämä yleiskuva on samalla perusta jokaiselle myöhemmälle muutokselle.

Tärkeimmät asetukset poolia kohden

Seuraava yleiskatsaus perustuu PHP-käsikirjan FPM-asetuksiin. Prosessien ja aikojen arvot määräytyvät kuormanne ja sovelluksenne mukaan:

Asetus Tarkoitus Suositus
user, group workerien käyttäjä oma käyttäjä sivustoa kohden, ei koskaan root
listen.owner, listen.group, listen.mode socketin oikeudet vain verkkopalvelimen ryhmä, tila 0660
listen.acl_users pääsy ACL:llä omistajan sijaan merkitkää vain verkkopalvelimen käyttäjä
security.limit_extensions suoritettavat päätteet rajatkaa arvoon .php (oletus .php .phar)
clear_env tyhjentää ympäristömuuttujat jättäkää oletukseen yes
pm.max_children workerien enimmäismäärä rajatkaa niin, ettei yksi sivusto kuormita palvelinta täyteen
request_terminate_timeout jumittuneiden pyyntöjen keskeytys asettakaa pisimmän oikeutetun pyynnön mukaan
pm.status_path, ping.path tila- ja ping-sivu asettakaa vain tarvittaessa ja suojatkaa sisäisesti
slowlog, request_slowlog_timeout hitaiden pyyntöjen loki poolia kohden omaan tiedostoon

Koventetun poolin ote näyttää tältä:

; /etc/php/8.3/fpm/pool.d/shop.conf (ote)
[shop]
user = shop
group = shop
listen = /run/php/shop.sock
listen.owner = www-data
listen.group = www-data
listen.mode = 0660

pm = dynamic
pm.max_children = 20
pm.start_servers = 4
pm.min_spare_servers = 2
pm.max_spare_servers = 6
request_terminate_timeout = 60s

security.limit_extensions = .php
clear_env = yes

slowlog = /var/log/php/shop.slow.log
request_slowlog_timeout = 10s
php_admin_value[error_log] = /var/log/php/shop.error.log

Asetukset kuten memory_limit tai session.upload_progress.enabled asetatte poolia kohden komennoilla php_admin_value ja php_admin_flag. Käsikirjan mukaan näitä arvoja ei voi ylikirjoittaa funktiolla ini_set(). Lisää kohdassa php_admin_value: asetusten lukitseminen ylikirjoitukselta.

Tilasivut ja workerien vaihto oikeaan asiayhteyteen

pm.status_path ja ping.path ovat aktiivisia vain, jos ne on asetettu. Tilasivu näyttää käynnissä olevat pyynnöt, prosessit ja kuormituksen. Valvonnassa se on hyödyllinen, mutta julkisesti saavutettavana tarpeeton tietolähde hyökkääjille. Ohjatkaa nämä polut verkkopalvelimessa vain sisäisille osoitteille. Miten Nginx ja PHP-FPM toimivat turvallisesti yhdessä, kuvaa Nginxin ja PHP-FPM:n suojaus.

pm.max_requests määrittää, minkä pyyntömäärän jälkeen worker käynnistyy uudelleen; oletus on 0, eli ei koskaan. Nollaa suurempi arvo auttaa hitaasti kasvavaa muistinkäyttöä vastaan. Suojaksi PHP2Shelliä vastaan sitä ei ole tarkoitettu: php.net ei mainitse sitä siirtymäajan toimenpiteiden joukossa ja korostaa, että vain päivitys suojaa täydellisesti. Päivityksen jälkeen pätee lisäksi: kaikkien poolien kaikki workerit on käynnistettävä uudelleen, koska vanhat prosessit muuten jatkavat haavoittuvalla koodilla.

Vinkki

Ylläpitäkää mallipohjaa uusille pooleille ja luokaa jokainen uusi sivusto sen avulla. Näin erottelu syntyy automaattisesti sen sijaan, että se rakennettaisiin jälkikäteen vuosien päästä.

Tyypillisiä virheitä muutoksessa

Yleisin virhe on uusi pooli, joka pyörii omalla käyttäjällään, mutta jonka tiedostot kuuluvat edelleen käyttäjälle www-data. Silloin pooli ei saa kirjoittaa sinne, minne sen pitää, ja joku asettaa oikeudet liian väljiksi. Selvittäkää etukäteen, mitkä kansiot on oltava kirjoitettavia. Toinen virhe ovat ajastetut tehtävät, jotka pyörivät yhä vanhan käyttäjän alla ja luovat tiedostoja väärällä omistajalla. Kolmas on kaikkien poolien yhteinen istuntokansio, joka kumoaa erottelun jälleen.

Testatkaa jokaisen muutoksen jälkeen sivuston kirjautuminen, upload-toiminnot, välimuistit ja ajastetut tehtävät ja seuratkaa poolin virhelokia.

Miten PHP SOS auttaa konkreettisesti?

  • Kartoitamme kaikki poolit, käyttäjät, socketit ja asetukset ja näytämme, missä sivustot nykyisin jakavat prosesseja tai oikeuksia.
  • Perustamme jokaiselle sivustolle koventetun poolin socket-oikeuksineen, päätterajoineen, resurssirajoineen ja omine lokeineen.
  • Suojaamme tilasivut, käynnistämme kaikki workerit hallitusti uudelleen ja testaamme jokaisen sivuston.
  • Palvelimen koventamisen yhteydessä dokumentoimme erottelun mallipohjaksi tuleville projekteille.

Usein kysytyt kysymykset

Miksi jokaisella sivustolla pitäisi olla oma PHP-FPM-pooli?

Oma pooli omalla järjestelmäkäyttäjällä erottaa sivustot toisistaan prosessien ja tiedosto-oikeuksien tasolla. Jos yksi sivusto vaarantuu, koodi ei voi vaikeuksitta lukea muiden tiedostoja. Lisäksi rajat ja asetukset voidaan määrittää sivustokohtaisesti.

Suojaako oma pooli PHP2Shelliltä?

Ei. Aukot ovat itse PHP-tulkissa, jota kaikki poolit käyttävät yhteisesti. Suojan antaa vain päivitys korjattuun versioon ja kaikkien workerien uudelleenkäynnistys. Erilliset poolit rajaavat kuitenkin sitä, kuinka pitkälle onnistunut hyökkäys ulottuu.

Mitä security.limit_extensions tekee?

PHP-käsikirjan mukaan asetus rajaa, mitkä tiedostopäätteet PHP-FPM suorittaa pääskriptinä. Oletus on .php ja .phar. Kun rajaatte sen päätteeseen .php, estätte esimerkiksi ladattujen kuvatiedostojen suorittamisen PHP:nä, jos verkkopalvelin on määritetty väärin.

Onko PHP-FPM:n tilasivu vaarallinen?

Se paljastaa yksityiskohtia käynnissä olevista prosesseista ja pyynnöistä. Jos se on julkisesti saavutettavissa ilman suojaa, se helpottaa hyökkääjien suunnistamista. Käsikirjan mukaan se on aktiivinen vain, kun pm.status_path on asetettu. Silloin verkkopalvelimen pitäisi rajata polku sisäisiin osoitteisiin.

Lähteet

Pikayhteys

Jokainen tunti on tärkeä. Kirjoittakaa meille nyt.

Kuvatkaa lyhyesti järjestelmä, PHP-versio ja havainnot. Otamme yhteyttä, selvitämme tilanteen ja työskentelemme etänä, kunnes tapaus on käsitelty loppuun ja dokumentoitu.

Pikaapu