Lühidalt: open_basedir piirab katalooge, millele PHP-l on juurdepääs. Üksi on see ainult täiendav tõke. Tõhus isolatsioon veebisaidi kaupa tekib alles koostoimes: oma süsteemikasutaja, oma PHP-FPM pool, oma ajutine kaust ja oma andmebaasi ligipääsud. Siis jääb sissemurdmine ühte veebisaiti selle saidiga piiratuks.
Miks isolatsioon otsustab pärast PHP2Shelli kahju üle
Paljudes serverites töötavad mitu veebisaiti kõrvuti: ettevõtte sait, pood, vana kampaaniasait, agentuuridel sageli kümneid klienditöid. Sageli jagavad need ühte süsteemikasutajat ja ühte PHP protsessi. Kui üks neist kompromiteeritakse, on kõik teised avatud.
PHP2Shell teeb selle riski käegakatsutavaks. Turvaaugud CVE-2026-109618 ja CVE-2026-109619 võimaldavad kahjuliku koodi käivitamist ilma sisselogimata, sõltumata sisuhaldussüsteemist. Meediaraportite kohaselt oli esimene rünnakukatse juba 17.10.2026, paigad järgnesid 21.10. Lahendus on uuendus. Kas rünnak tabab sellele eelneval ajal ühte või kümmet veebisaiti, otsustab aga isolatsioon.
Just teise turvaaugu puhul lisandub veel üks mõte: PHP projekti andmetel võib päringu sisemine seisund jääda töötajasse (worker) alles ja seda võib kasutada hilisem päring samas töötajas. Veebisaitide kaupa lahutatud poolid tagavad, et veebisaidid ei jaga töötajaid niikuinii.
Mida open_basedir annab
Seadega open_basedir määrate katalooge loendi. PHP failifunktsioonid, nagu fopen, include või file_get_contents, keelduvad siis juurdepääsust kõigele väljaspool seda loendit. Sissetoodud skript ei saa nii lihtsalt lugeda naaberveebisaidi seadistusfaile.
Piirid on olulised: kontroll toimub PHP sees. Programmid, mis käivitatakse väljaspool PHP-d, sellele ei allu, ja vead interpretaatoris võivad seda kõrvale kalduda. Seetõttu kuulub open_basedir alati kokku lukustatud süsteemifunktsioonidega, nagu on kirjeldatud juhendis disable_functions õige kasutamine, ja eelkõige lahutusega operatsioonisüsteemi tasemel.
Isolatsioon veebisaidi kaupa neljas kihis
Vastupidav lahutus ehitub mitmele kihile. Iga kiht püüab kinni selle, mida eelmine ei suuda.
| Kiht | Meede | Mõju |
|---|---|---|
| Operatsioonisüsteem | iga veebisaidi oma süsteemikasutaja | teiste veebisaitide faile ei saa lugeda |
| PHP protsessid | oma PHP-FPM pool oma sokliga | ühist töötajat ei ole, oma seaded |
| PHP seadistus | open_basedir, oma tmp- ja sessioonikaust |
täiendav tõke, ühiseid ajutisi faile ei ole |
| Andmed | oma andmebaasikasutaja õigustega ainult oma andmebaasile | juurdepääsu võõrastele klientide andmetele ei ole |
Kõrge kaitsevajaduse korral, näiteks maksetöötlusega poodide või terviseandmetega portaalide puhul, lisanduvad konteinerid või eraldi serverid.
open_basedir seadistamine PHP-FPM-i poolis
Järgmine näide näitab ühe veebisaidi poolit oma kasutajaga seite1. Teed ja versiooninumbri kohandage oma süsteemile.
; /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
Viimane rida seab kohe ka php.net-i PHP2Shelli üleminekumeetme. See toimib ainult poolist, php.ini-st või serveri seadistusest, mitte käsuga ini_set() ega failiga .user.ini. Kaustad loote sobivate õigustega:
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
Kuidas peaksid õigused tegelikus veebikataloogis välja nägema, kirjeldab juhend Failiõigused veebiserveris.
Veebiserveri ühendamine ja tulemuse kontroll
Nginxis viitab iga veebisait oma sokkelile. Nii ei satu ükski päring teise veebisaidi poolile.
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;
}
}
Lisavihjeid selle kombinatsiooni kohta leiate lehelt Nginxi ja PHP-FPM-i turvamine. Pärast taaskäivitust kontrollige, kas poolid tõesti eraldi töötavad:
sudo systemctl restart php8.3-fpm
# Iga pool peaks töötama oma kasutaja all
ps -eo user,pid,cmd | grep "[p]hp-fpm: pool"
Testige seejärel kõiki veebisaidi funktsioone: üleslaadimised, piltide töötlemine, vahemälud, ajastatud ülesanded. Vealogis olevad teated viitega open_basedir restriction näitavad, milline tee veel puudub. Lisage ainult teed, mida rakendus tõesti vajab, ja mitte kunagi kogu failisüsteemi.
Paljude klientide saitidega agentuurid peaksid hoidma poolide seadistust mallina. Nii saab iga uus veebisait lahutuse automaatselt, mitte ei pea seda hiljem järele varustama. Selle juhtumi taustainfo leiate lehelt Turvapartner agentuuridele.
Tüüpilised komistuskivid üleminekul
Üleminek lahutatud poolidele on planeeritav, kuid sellel on mõned korduvad lõksud. Kõige sagedasem puudutab ühiselt kasutatavaid teeke: kui näiteks raamistik või fontidega kaust asub väljaspool veebisaidi kataloogi, tuleb see tee lugemiseks open_basedir-i lisada. Parem on selliseid sõltuvusi projekti enda sisse tuua.
Teine lõks on sessioonid. Kui salvestuskoht muutub, logitakse kõik külastajad korra välja ja pooleliolevad ostukorvid lähevad kaotsi. Planeerige üleminek seetõttu rahulikku ajaaknasse ja teatage sellest sisemiselt.
Kolmandaks töötavad ajastatud ülesanded sageli käsurea kaudu ja seega teise kasutaja all kui veebisait. Kontrollige cron-ülesandeid ja järjekordi ning laske neil töötada veebisaidi uue kasutaja all, muidu tekivad valesse omanikku kuuluvad failid, mida PHP hiljem enam muuta ei tohi.
Lõpuks peaks igal poolil olema oma piirangud protsessidele ja mälule. Veebisait, mis koormuse või rünnaku alla satub, ei suuda nii teisi endaga kaasa tõmmata.
Kuidas PHP SOS konkreetselt aitab?
- Kaardistame, millised veebisaidid jagavad täna kasutajaid, protsesse ja andmebaase.
- Seame iga veebisaidi jaoks üles oma kasutajad, poolid, ajutised kaustad ja andmebaasi ligipääsud, rakendusi muutmata.
- Testime iga veebisaiti pärast üleminekut ja kõrvaldame puuduvad teed sihipäraselt.
- Dokumenteerime lahutuse mallina tulevaste projektide jaoks.
Kuidas see sobitub tervikkontseptsiooni, kirjeldab teenus Serveri karastamine PHP veebiserveritele.
Korduma kippuvad küsimused
Kas open_basedir-ist piisab veebisaitide üksteisest lahutamiseks?
Ei. open_basedir on täiendav tõke PHP sees, mitte range lahutus. Isolatsioon muutub usaldusväärseks alles iga veebisaidi oma süsteemikasutajate ja poolidega, suurema kaitsevajaduse korral konteinerite või eraldi serveritega.
Miks ei tööta pärast open_basedir seadmist üleslaadimised enam?
Enamasti puudub loendist ajutiste failide kaust. Looge igale veebisaidile oma tmp-kaust, kandke see open_basedir-i ja seadke upload_tmp_dir ning sys_temp_dir sellele kaustale.
Kas rakendus saab open_basedir-i ise tühistada?
Rakendus saab seadet tööajal ainult edasi piirata, mitte leevendada. Seadke open_basedir siiski käsuga php_admin_value poolis, et väärtus oleks üheselt fikseeritud.
Kas isolatsioon on võimalik ka jagatud veebimajutuses?
See sõltub veebimajutajast. Paljud pakkumised lahutavad kliendid oma kasutajate ja PHP protsesside kaudu. Küsige järele, kuidas lahutus on teostatud, eriti kui mitu teie veebisaiti asuvad ühes paketis.