Ukratko: open_basedir ograničava direktorije kojima PHP smije pristupati. Sam po sebi to je samo dodatna prepreka. Učinkovita izolacija po web-stranici nastaje tek u međudjelovanju: zaseban sistemski korisnik, zaseban PHP-FPM pool, zasebna tmp mapa i zasebni pristupi bazi podataka. Tada provala u jednu web-stranicu ostaje ograničena na tu web-stranicu.
Zašto izolacija nakon PHP2Shella odlučuje o šteti
Na mnogim poslužiteljima paralelno radi više web-stranica: stranica tvrtke, shop, stara stranica kampanje, kod agencija često deseci projekata klijenata. Često dijele jednog sistemskog korisnika i jedan PHP proces. Ako je jedna kompromitirana, sve ostale ostaju otkrivene.
PHP2Shell taj rizik čini opipljivim. Ranjivosti CVE-2026-109618 i CVE-2026-109619 omogućuju izvršavanje zlonamjernog koda bez prijave, neovisno o CMS-u. Prema medijskim izvješćima prvi pokušaj napada bio je već 17.10.2026., a zakrpe su uslijedile 21.10. Rješenje je ažuriranje. Hoće li napad u razdoblju prije toga pogoditi jednu ili deset web-stranica, ipak odlučuje izolacija.
Kod druge ranjivosti dolazi još jedna misao: prema PHP projektu interno stanje zahtjeva može ostati u workeru i upotrijebiti ga kasniji zahtjev u istom workeru. Odvojeni poolovi po web-stranici osiguravaju da web-stranice ionako ne dijele workere.
Što open_basedir postiže
Uz open_basedir određujete popis direktorija. PHP funkcije za datoteke poput fopen, include ili file_get_contents tada odbijaju pristup svemu izvan tog popisa. Ubačena skripta tako ne može tek tako čitati konfiguracijske datoteke susjedne web-stranice.
Granice su važne: provjera se odvija unutar PHP-a. Programi pokrenuti izvan PHP-a joj ne podliježu, a pogreške u interpreteru mogu je zaobići. Zato open_basedir uvijek treba ići zajedno sa zabranjenim sistemskim funkcijama, kako opisuje vodič Ispravna uporaba disable_functions, i prije svega s razdvajanjem na razini operacijskog sustava.
Izolacija po web-stranici u četiri sloja
Pouzdano razdvajanje gradi se na više slojeva. Svaki zahvaća ono što prethodni ne postiže.
| Sloj | Mjera | Učinak |
|---|---|---|
| Operacijski sustav | zaseban sistemski korisnik po web-stranici | Datoteke drugih web-stranica nisu čitljive |
| PHP procesi | zaseban PHP-FPM pool sa zasebnim socketom | nema zajedničkog workera, vlastite postavke |
| PHP konfiguracija | open_basedir, zasebna tmp mapa i mapa sesija |
dodatna prepreka, nema zajedničkih privremenih datoteka |
| Podaci | zaseban korisnik baze podataka s pravima samo na vlastitu bazu | nema pristupa tuđim podacima klijenata |
Kod visoke potrebe za zaštitom, primjerice kod shopova s naplatom ili portala sa zdravstvenim podacima, dolaze kontejneri ili odvojeni poslužitelji.
Konfiguracija open_basedir u PHP-FPM poolu
Sljedeći primjer prikazuje pool za web-stranicu sa zasebnim korisnikom seite1. Putanje i broj verzije prilagodite svom sustavu.
; /etc/php/8.3/fpm/pool.d/seite1.conf
[seite1]
user = seite1
group = seite1
listen = /run/php/seite1.sock
listen.owner = www-data
listen.group = www-data
listen.mode = 0660
pm = ondemand
pm.max_children = 10
php_admin_value[open_basedir] = /var/www/seite1/:/var/www/seite1-tmp/
php_admin_value[upload_tmp_dir] = /var/www/seite1-tmp/
php_admin_value[sys_temp_dir] = /var/www/seite1-tmp/
php_admin_value[session.save_path] = /var/www/seite1-tmp/sessions
php_admin_value[error_log] = /var/log/php/seite1.error.log
php_admin_flag[session.upload_progress.enabled] = off
Zadnji redak odmah postavlja PHP2Shell privremenu mjeru s php.neta. Ona djeluje samo iz poola, php.ini ili konfiguracije poslužitelja, a ne putem ini_set() ili .user.ini. Mape napravite s odgovarajućim pravima:
sudo useradd --system --home /var/www/seite1 --shell /usr/sbin/nologin seite1
sudo mkdir -p /var/www/seite1-tmp/sessions
sudo chown -R seite1:seite1 /var/www/seite1-tmp
sudo chmod 700 /var/www/seite1-tmp
Kako bi prava u samom web-direktoriju trebala izgledati, opisuje vodič Prava datoteka na web-poslužitelju.
Povezivanje web-poslužitelja i provjera rezultata
U Nginxu svaka web-stranica upućuje na vlastiti socket. Tako nijedan zahtjev ne završava u poolu druge web-stranice.
server {
server_name seite1.example;
root /var/www/seite1/public;
location ~ \.php$ {
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass unix:/run/php/seite1.sock;
}
}
Dodatne napomene o toj kombinaciji nalaze se na stranici Zaštita Nginxa s PHP-FPM-om. Nakon ponovnog pokretanja provjerite rade li poolovi zaista odvojeno:
sudo systemctl restart php8.3-fpm
# Svaki pool trebao bi raditi pod vlastitim korisnikom
ps -eo user,pid,cmd | grep "[p]hp-fpm: pool"
Zatim testirajte sve funkcije web-stranice: uploade, obradu slika, cacheve, planirane zadatke. Poruke o pogrešci s naznakom open_basedir restriction u logu pogrešaka pokazuju koja putanja još nedostaje. Dodajte samo putanje koje aplikacija zaista treba, a nikada cijeli datotečni sustav.
Agencije s mnogo stranica klijenata trebale bi konfiguraciju poola održavati kao predložak. Tako svaka nova web-stranica automatski dobiva razdvajanje umjesto da se naknadno dograđuje. Pozadinu za taj slučaj nalazite na stranici Sigurnosni partner za agencije.
Tipične zamke pri prelasku
Prelazak na odvojene poolove je planabilan, ali ima nekoliko ponavljajućih zamki. Najčešća se tiče zajednički korištenih biblioteka: ako se primjerice framework ili mapa s fontovima nalazi izvan direktorija web-stranice, taj se put mora u open_basedir uključiti za čitanje. Bolje je takve ovisnosti dovesti u sam projekt.
Druga zamka su sesije. Ako se mjesto pohrane promijeni, svi posjetitelji jednom su odjavljeni, a košarice koje su u tijeku nestaju. Prelazak stoga planirajte u mirnom vremenskom prozoru i najavite ga interno.
Treće, planirani zadaci često se izvršavaju preko naredbenog retka i time pod drugim korisnikom od web-stranice. Provjerite cron zadatke i redove čekanja i pokrećite ih pod novim korisnikom web-stranice, inače nastaju datoteke s pogrešnim vlasnikom koje PHP kasnije više ne smije mijenjati.
Naposljetku, svaki bi pool trebao imati vlastite granice za procese i memoriju. Web-stranica koja dođe pod opterećenje ili napad tako druge ne može povući sa sobom.
Kako PHP SOS konkretno pomaže?
- Utvrđujemo koje web-stranice danas dijele korisnike, procese i baze podataka.
- Za svaku web-stranicu postavljamo zasebne korisnike, poolove, tmp mape i pristupe bazi podataka, bez izmjena aplikacija.
- Testiramo svaku web-stranicu nakon prelaska i ciljano otklanjamo putanje koje nedostaju.
- Razdvajanje dokumentiramo kao predložak za buduće projekte.
Kako se to uklapa u cjelovit koncept, opisuje usluga Ojačavanje poslužitelja za PHP web-poslužitelje.
Česta pitanja
Je li open_basedir dovoljan za razdvajanje web-stranica?
Ne. open_basedir je dodatna prepreka unutar PHP-a, a ne tvrdo razdvajanje. Izolacija postaje pouzdana tek sa zasebnim sistemskim korisnicima i poolovima po web-stranici, a kod veće potrebe za zaštitom s kontejnerima ili odvojenim poslužiteljima.
Zašto nakon postavljanja open_basedir uploadi više ne rade?
Najčešće na popisu nedostaje mapa za privremene datoteke. Za svaku web-stranicu napravite zasebnu tmp mapu, upišite je u open_basedir i postavite upload_tmp_dir i sys_temp_dir na tu mapu.
Može li aplikacija sama ukinuti open_basedir?
Aplikacija postavku tijekom rada može samo dodatno suziti, a ne ublažiti. Ipak postavite open_basedir putem php_admin_value u poolu kako bi vrijednost bila nedvosmisleno određena.
Je li izolacija moguća i kod shared hostinga?
To ovisi o pružatelju hostinga. Mnoge ponude razdvajaju klijente zasebnim korisnicima i PHP procesima. Pitajte kako je razdvajanje provedeno, osobito ako se više Vaših web-stranica nalazi u jednom paketu.