# open_basedir ir izoliacija kiekvienai svetainei

> Teisingai nustatykite open_basedir ir atskirkite svetaines: savas naudotojas, savas PHP-FPM baseinas, savi laikini aplankai. Su Nginx pavyzdžiu.

Šaltinis: https://phpsos.de/lt/ratgeber/open-basedir/  
Būsena: 2026-10-25  
Teikėjas: PHP SOS, PHP avarinė pagalba ir serverio sauga. Skubi pagalba per „WhatsApp“: https://wa.me/491736494914?text=Sveiki%2C%20PHP%20SOS%2C%20mums%20reikia%20pagalbos%20su%20m%C5%ABs%C5%B3%20PHP%20serveriu.%20%C4%AEmon%C4%97%3A%20%E2%80%A6%20Svetain%C4%97%3A%20%E2%80%A6

**Trumpai:** `open_basedir` apriboja katalogus, prie kurių PHP gali kreiptis. Vienas jis yra tik papildomas barjeras. Veiksminga izoliacija kiekvienai svetainei atsiranda tik kartu: savas sistemos naudotojas, savas PHP-FPM baseinas, savas laikinų failų aplankas ir savos duomenų bazės prieigos. Tuomet įsilaužimas į vieną svetainę lieka toje svetainėje.

## Kodėl po PHP2Shell izoliacija lemia žalą

Daugelyje serverių greta veikia kelios svetainės: įmonės svetainė, parduotuvė, sena kampanijos svetainė, o agentūrose dažnai dešimtys klientų projektų. Dažnai jos dalijasi vienu sistemos naudotoju ir vienu PHP procesu. Jei viena kompromituojama, visos kitos atviros.

PHP2Shell šią riziką padaro apčiuopiamą. Pažeidžiamumai CVE-2026-109618 ir CVE-2026-109619 leidžia vykdyti kenkėjišką kodą be prisijungimo, nepriklausomai nuo CMS. Pasak žiniasklaidos pranešimų, pirmasis atakos bandymas buvo jau 2026-10-17, o pataisos pasirodė spalio 21 d. Sprendimas yra atnaujinimas. Bet ar ataka tuo prieš tai laikotarpiu paliečia vieną ar dešimt svetainių, lemia izoliacija.

Ypač dėl antrojo pažeidžiamumo atsiranda dar viena mintis: pasak PHP projekto, vidinė užklausos būsena gali išlikti darbiniame procese (worker) ir būti panaudota vėlesnės užklausos tame pačiame darbiniame procese. Atskiri baseinai kiekvienai svetainei užtikrina, kad svetainės darbinių procesų vis tiek nesidalija.

## Ką daro open_basedir

Su `open_basedir` nustatote katalogų sąrašą. PHP failų funkcijos, tokios kaip `fopen`, `include` ar `file_get_contents`, tuomet atsisako prieigos prie visko už šio sąrašo ribų. Įterptas skriptas taip negali be didesnių kliūčių skaityti kaimyninės svetainės konfigūracijos failų.

Ribos svarbios: patikra vyksta PHP viduje. Programoms, paleistoms už PHP ribų, ji netaikoma, o interpretatoriaus klaidos gali ją apeiti. Todėl `open_basedir` visada turi derėti su užblokuotomis sistemos funkcijomis, kaip aprašyta vadove [Kaip teisingai naudoti disable_functions](https://phpsos.de/lt/ratgeber/disable-functions/), ir visų pirma su atskyrimu operacinės sistemos lygiu.

## Izoliacija kiekvienai svetainei keturiais sluoksniais

Patikimas atskyrimas remiasi keliais sluoksniais. Kiekvienas sustabdo tai, ko ankstesnis nepadaro.

| Sluoksnis | Priemonė | Poveikis |
|---|---|---|
| Operacinė sistema | savas sistemos naudotojas kiekvienai svetainei | Kitų svetainių failų skaityti negalima |
| PHP procesai | savas PHP-FPM baseinas su savu lizdu (socket) | Nėra bendro darbinio proceso, savi nustatymai |
| PHP konfigūracija | `open_basedir`, savas laikinų failų ir sesijų aplankas | papildomas barjeras, jokių bendrų laikinų failų |
| Duomenys | savas duomenų bazės naudotojas su teisėmis tik į savo duomenų bazę | Jokios prieigos prie svetimų klientų duomenų |

Esant dideliam apsaugos poreikiui, pavyzdžiui, parduotuvėse su mokėjimų apdorojimu ar portaluose su sveikatos duomenimis, prisideda konteineriai ar atskiri serveriai.

## open_basedir konfigūravimas PHP-FPM baseine

Toliau pateiktas pavyzdys rodo baseiną svetainei su savu naudotoju `seite1`. Kelius ir versijos numerį pritaikykite savo sistemai.

```ini
; /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
```

Paskutinė eilutė kartu nustato php.net pereinamąją PHP2Shell priemonę. Ji veikia tik iš baseino, php.ini ar serverio konfigūracijos, o ne per `ini_set()` ar `.user.ini`. Aplankus sukurkite su tinkamomis teisėmis:

```bash
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
```

Kaip turėtų atrodyti teisės pačiame žiniatinklio kataloge, aprašo vadovas [Failų teisės žiniatinklio serveryje](https://phpsos.de/lt/ratgeber/dateirechte-webserver/).

## Žiniatinklio serverio prijungimas ir rezultato patikra

Nginx kiekviena svetainė nurodo savo lizdą. Taip jokia užklausa nepatenka į kitos svetainės baseiną.

```nginx
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;
    }
}
```

Daugiau patarimų šiam deriniui rasite puslapyje [Nginx su PHP-FPM apsauga](https://phpsos.de/lt/server/nginx-php-fpm/). Po paleidimo iš naujo patikrinkite, ar baseinai tikrai veikia atskirai:

```bash
sudo systemctl restart php8.3-fpm
# Kiekvienas baseinas turėtų veikti savo naudotoju
ps -eo user,pid,cmd | grep "[p]hp-fpm: pool"
```

Po to išbandykite visas svetainės funkcijas: įkėlimus, paveikslėlių apdorojimą, talpyklas, suplanuotas užduotis. Klaidų žurnalo pranešimai su nuoroda į `open_basedir restriction` parodo, kurio kelio dar trūksta. Pridėkite tik kelius, kurių programai tikrai reikia, ir niekada visos failų sistemos.

> **Patarimas:**
> Agentūros su daugybe klientų svetainių baseinų konfigūraciją turėtų prižiūrėti kaip šabloną. Taip kiekviena nauja svetainė atskyrimą gauna automatiškai, o ne vėliau jį reikia pritaikyti. Pagrindą tam atvejui rasite puslapyje [Saugumo partneris agentūroms](https://phpsos.de/lt/branchen/agenturen-white-label/).

## Tipinės kliūtys pereinant

Perėjimas prie atskirų baseinų planuojamas, bet turi keletą pasikartojančių spąstų. Dažniausias susijęs su bendrai naudojamomis bibliotekomis: jei, pavyzdžiui, karkasas (framework) ar šriftų aplankas yra už svetainės katalogo ribų, šį kelią reikia įtraukti į `open_basedir` tik skaitymui. Geriau tokias priklausomybes perkelti į patį projektą.

Antrieji spąstai yra sesijos. Pasikeitus saugojimo vietai, visi lankytojai vieną kartą atjungiami, o vykstantys prekių krepšeliai prarandami. Todėl perėjimą planuokite ramiu laiku ir paskelbkite jį viduje.

Trečia, suplanuotos užduotys dažnai vykdomos per komandinę eilutę, taigi kitu naudotoju nei svetainė. Patikrinkite cron užduotis ir eiles ir leiskite joms veikti naujo svetainės naudotojo teisėmis, kitaip atsiranda failų su netinkamu savininku, kurių PHP vėliau nebegali keisti.

Galiausiai kiekvienas baseinas turėtų turėti savas procesų ir atminties ribas. Svetainė, kuriai kyla apkrova ar kuri atakuojama, taip negali parklupdyti kitų.

## Kaip PHP SOS padeda konkrečiai?

- Nustatome, kurios svetainės šiandien dalijasi naudotojais, procesais ir duomenų bazėmis.
- Kiekvienai svetainei įrengiame savus naudotojus, baseinus, laikinų failų aplankus ir duomenų bazės prieigas, nekeisdami programų.
- Po perėjimo išbandome kiekvieną svetainę ir tikslingai ištaisome trūkstamus kelius.
- Atskyrimą dokumentuojame kaip šabloną būsimiems projektams.

Kaip tai telpa į bendrą koncepciją, aprašo paslauga [PHP žiniatinklio serverių sutvirtinimas](https://phpsos.de/lt/leistungen/server-haertung/).


## Dažni klausimai

**Ar open_basedir pakanka svetainėms atskirti?**  
Ne. open_basedir yra papildomas barjeras PHP viduje, o ne tvirtas atskyrimas. Patikima izoliacija atsiranda tik su atskirais sistemos naudotojais ir baseinais kiekvienai svetainei, o esant didesniam apsaugos poreikiui su konteineriais ar atskirais serveriais.

**Kodėl nustačius open_basedir nebeveikia įkėlimai?**  
Dažniausiai sąraše trūksta aplanko laikiniems failams. Kiekvienai svetainei sukurkite savo laikinų failų aplanką, įrašykite jį į open_basedir ir nustatykite upload_tmp_dir bei sys_temp_dir į šį aplanką.

**Ar programa pati gali panaikinti open_basedir?**  
Programa vykdymo metu nustatymą gali tik dar labiau apriboti, bet ne sušvelninti. Vis tiek nustatykite open_basedir per php_admin_value baseine, kad reikšmė būtų vienareikšmiškai užfiksuota.

**Ar izoliacija įmanoma ir bendrinamame hostinge?**  
Tai priklauso nuo hostingo teikėjo. Daugelis pasiūlymų klientus atskiria savais naudotojais ir PHP procesais. Paklauskite, kaip atskyrimas įgyvendintas, ypač kai keletas jūsų svetainių yra viename pakete.

## Šaltiniai

- [php.net: saugumo pranešimai](https://www.php.net/)
- [OWASP Cheat Sheet Series](https://cheatsheetseries.owasp.org/)
- [BSI IT-Grundschutz](https://www.bsi.bund.de/DE/Themen/Unternehmen-und-Organisationen/Standards-und-Zertifizierung/IT-Grundschutz/it-grundschutz_node.html)
