Trenutno stanje: PHP2Shell. Dvije kritične PHP ranjivosti (CVSS 9.2) omogućuju zlonamjerni kod bez prijave. Zakrpe od 21. 10. 2026.Što sada učiniti →

Izolacija PHP-FPM poolova po web-stranici

Zaseban pool za svaku web-stranicu početak je, a ne kraj. Evo kako provjeriti postojeće poolove i ojačati socketove, ekstenzije, status stranice, resurse i zapisnike.

Stanje 5 min čitanjaOjačavanje i konfiguracija

Ukratko: Svaka web-stranica na poslužitelju trebala bi imati zaseban PHP-FPM pool sa zasebnim sistemskim korisnikom i zasebnim socketom. Razdvajanje postaje djelotvorno tek s pojedinostima: prava na socket samo za web-poslužitelj, security.limit_extensions na .php, nikakve javno dostupne status stranice, vlastite granice za procese i trajanje te odvojeni zapisnici. Od samog PHP2Shella štiti samo ažuriranje; poolovi ograničavaju koliko daleko napad doseže.

Jedan poslužitelj, mnogo web-stranica, zajednički rizik

Na mnogim se poslužiteljima tijekom godina nakupilo ono što nitko nije tako planirao. Web-stranica tvrtke, shop, kampanjska stranica iz 2019. i testni sustav rade jedni uz druge, često pod istim korisnikom i u istom poolu. Ako se zaboravljena kampanjska stranica kompromitira, otvoreni su i podaci kupaca shopa.

PHP-FPM, FastCGI upravitelj procesa za PHP, to rješava poolovima: skupinama worker procesa s vlastitim postavkama. Kako funkcionira osnovno načelo, objašnjava članak PHP-FPM objašnjen: upravitelj procesa, poolovi i workeri. Izgradnju odvojenih poolova sa zasebnim korisnikom, zasebnom privremenom mapom i open_basedir opisuje vodič open_basedir i izolacija po web-stranici. Ovaj članak ide korak dalje: kako provjeriti postojeće poolove i koje postavke razdvajanje čine otpornim?

Važno za svrstavanje: kod PHP2Shella ranjivosti CVE-2026-109618 i CVE-2026-109619 nalaze se u PHP interpreteru koji dijele svi poolovi jedne verzije PHP-a. Zaseban pool ne sprječava iskorištavanje. Ali odlučuje hoće li napadač nakon toga doseći jednu web-stranicu ili sve.

PHP-FPM poolovi sa zasebnim korisnikom: provjera postojećeg stanja

Prije nego išta promijenite, steknite pregled. Sljedeće naredbe samo čitaju. Putovi i brojevi verzija razlikuju se po distribuciji:

# Svi poolovi s korisnikom i socketom
grep -HE '^\s*(\[|user|group|listen)\s*' /etc/php/*/fpm/pool.d/*.conf

# Pokrenuti poolovi i njihovi korisnici
ps -eo user,pid,cmd | grep '[p]hp-fpm: pool'

# Socketi i njihova prava
ls -l /run/php/

# Provjeriti konfiguraciju na pogreške (ništa ne mijenja)
sudo php-fpm8.3 -t

Pazite na tri obrasca: više web-stranica u istom poolu, poolove koji rade kao www-data ili čak kao root te socketove u koje smiju pisati svi korisnici. Svaki od njih potkopava razdvajanje.

Ako na poslužitelju radi više verzija PHP-a, svaka ima vlastitu FPM uslugu s vlastitim direktorijima poolova. Provjerite sve, a ne samo verziju koju ste posljednju postavili. Upravo su stare verzije sa zaboravljenim poolovima rizik jer se često niti održavaju niti ponovno pokreću nakon ažuriranja. Napomene o tome nalaze se u članku Više verzija PHP-a na jednom poslužitelju. Rezultat zabilježite u maloj tablici: web-stranica, pool, korisnik, socket, verzija PHP-a. Taj je pregled ujedno osnova za svaku kasniju izmjenu.

Najvažnije postavke po poolu

Sljedeći pregled oslanja se na FPM konfiguraciju u PHP priručniku. Vrijednosti za procese i vremena ovise o Vašem opterećenju i aplikaciji:

Postavka Svrha Preporuka
user, group korisnik workera zaseban korisnik za svaku web-stranicu, nikad root
listen.owner, listen.group, listen.mode prava na socketu samo grupa web-poslužitelja, način 0660
listen.acl_users pristup putem ACL-a umjesto vlasnika upisati samo korisnika web-poslužitelja
security.limit_extensions ekstenzije koje se izvršavaju ograničiti na .php (zadano .php .phar)
clear_env isprazniti varijable okruženja ostaviti na zadanom yes
pm.max_children najveći broj workera ograničiti tako da jedna web-stranica ne zauzme cijeli poslužitelj
request_terminate_timeout prekid zapelih zahtjeva postaviti prema najdužem legitimnom zahtjevu
pm.status_path, ping.path status i ping stranica postaviti samo ako je potrebno i interno zaštititi
slowlog, request_slowlog_timeout zapisnik sporih zahtjeva po poolu u zasebnu datoteku

Izvadak za ojačani pool izgleda ovako:

; /etc/php/8.3/fpm/pool.d/shop.conf (izvadak)
[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

Postavke poput memory_limit ili session.upload_progress.enabled zadajte po poolu pomoću php_admin_value i php_admin_flag. Prema priručniku te se vrijednosti ne mogu nadjačati putem ini_set(). Više o tome u članku php_admin_value: zaključati postavke od nadjačavanja.

Status stranice i izmjena workera: ispravno svrstavanje

pm.status_path i ping.path aktivni su samo ako su postavljeni. Status stranica prikazuje pokrenute zahtjeve, procese i opterećenje. Za nadzor je korisna, ali javno dostupna nepotreban je izvor informacija za napadače. Te putanje u web-poslužitelju prosljeđujte samo za interne adrese. Kako Nginx i PHP-FPM sigurno surađuju, opisuje članak Zaštititi Nginx s PHP-FPM-om.

pm.max_requests određuje nakon koliko zahtjeva se worker ponovno pokreće; zadano je 0, dakle nikad. Vrijednost veća od nule pomaže protiv sporo rastuće potrošnje memorije. Kao zaštita od PHP2Shella nije zamišljena: php.net ga ne navodi među prijelaznim mjerama i naglašava da potpuno štiti samo ažuriranje. Nakon ažuriranja vrijedi i ovo: svi workeri svih poolova moraju se ponovno pokrenuti jer inače stari procesi nastavljaju raditi s ranjivim kodom.

Savjet

Održavajte predložak za nove poolove i svaku novu web-stranicu postavljajte pomoću njega. Tako razdvajanje nastaje automatski, umjesto da se godinama kasnije naknadno dograđuje.

Tipične pogreške pri prelasku

Najčešća je pogreška novi pool koji doduše radi pod vlastitim korisnikom, ali čije datoteke i dalje pripadaju korisniku www-data. Tada pool ne smije pisati gdje mora i netko prava postavi preširoko. Unaprijed razjasnite koje mape moraju biti zapisive. Druga su pogreška planirani zadaci koji i dalje rade pod starim korisnikom i stvaraju datoteke s pogrešnim vlasnikom. Treća je zajednička mapa sesija za sve poolove, koja razdvajanje ponovno ukida.

Nakon svake izmjene testirajte prijavu, prijenose, predmemorije i planirane zadatke web-stranice te pratite zapisnik pogrešaka poola.

Kako PHP SOS konkretno pomaže?

  • Bilježimo sve poolove, korisnike, socketove i postavke i pokazujemo gdje web-stranice danas dijele procese ili prava.
  • Za svaku web-stranicu postavljamo ojačani pool, s pravima na socket, granicom ekstenzija, granicama resursa i vlastitim zapisnicima.
  • Zaštićujemo status stranice, kontrolirano ponovno pokrećemo sve workere i testiramo svaku web-stranicu.
  • U sklopu ojačavanja poslužitelja razdvajanje dokumentiramo kao predložak za buduće projekte.

Česta pitanja

Zašto bi svaka web-stranica trebala imati zaseban PHP-FPM pool?

Zaseban pool sa zasebnim sistemskim korisnikom razdvaja web-stranice na razini procesa i prava nad datotekama. Ako se jedna web-stranica kompromitira, kod ne može bez daljnjega čitati datoteke drugih. Uz to se granice i postavke mogu odvojeno zadati za svaku web-stranicu.

Štiti li zaseban pool od PHP2Shella?

Ne. Ranjivosti su u samom PHP interpreteru koji svi poolovi dijele. Zaštitu pruža samo ažuriranje na ispravljenu verziju uz ponovno pokretanje svih workera. Odvojeni poolovi ipak ograničavaju koliko daleko doseže uspješan napad.

Što postiže security.limit_extensions?

Prema PHP priručniku postavka ograničava koje ekstenzije datoteka PHP-FPM izvršava kao glavnu skriptu. Zadano je .php i .phar. Tko je ograniči na .php, sprječava da se primjerice učitane slikovne datoteke izvršavaju kao PHP ako je web-poslužitelj pogrešno konfiguriran.

Je li status stranica PHP-FPM-a opasna?

Otkriva pojedinosti o pokrenutim procesima i zahtjevima. Ako je javno dostupna bez zaštite, napadačima olakšava orijentaciju. Prema priručniku aktivna je samo ako je postavljen pm.status_path. Tada bi web-poslužitelj trebao ograničiti putanju na interne adrese.

Izvori

Hitni kontakt

Svaki sat se računa. Pišite nam odmah.

Ukratko opišite sustav, verziju PHP-a i opažanje. Javit ćemo Vam se, razjasniti situaciju i raditi na daljinu dok incident nije zaključen i dokumentiran.

Hitna pomoć