# open_basedir и изолация за всеки уебсайт

> Правилно задаване на open_basedir и разделяне на уебсайтовете: отделен потребител, PHP-FPM пул и temp папки. С примерна конфигурация за Nginx.

Източник: https://phpsos.de/bg/ratgeber/open-basedir/  
Актуалност: 25.10.2026  
Доставчик: PHP SOS, Спешна помощ за PHP и сигурност на сървъри. Незабавна помощ по WhatsApp: https://wa.me/491736494914?text=%D0%97%D0%B4%D1%80%D0%B0%D0%B2%D0%B5%D0%B9%D1%82%D0%B5%2C%20PHP%20SOS%2C%20%D0%B8%D0%BC%D0%B0%D0%BC%D0%B5%20%D0%BD%D1%83%D0%B6%D0%B4%D0%B0%20%D0%BE%D1%82%20%D0%BF%D0%BE%D0%BC%D0%BE%D1%89%20%D1%81%20%D0%BD%D0%B0%D1%88%D0%B8%D1%8F%20PHP%20%D1%81%D1%8A%D1%80%D0%B2%D1%8A%D1%80.%20%D0%A4%D0%B8%D1%80%D0%BC%D0%B0%3A%20%E2%80%A6%20%D0%A3%D0%B5%D0%B1%D1%81%D0%B0%D0%B9%D1%82%3A%20%E2%80%A6

**Накратко:** `open_basedir` ограничава директориите, до които PHP има достъп. Сама по себе си това е само допълнителна бариера. Ефективна изолация за всеки уебсайт се получава едва от взаимодействието: отделен системен потребител, отделен PHP-FPM пул, отделна temp папка и отделни достъпи до базата данни. Тогава проникването в един уебсайт остава ограничено до него.

## Защо изолацията след PHP2Shell решава какви са щетите

На много сървъри работят няколко уебсайта един до друг: фирменият сайт, магазин, стара кампанийна страница, а при агенциите често десетки клиентски проекта. Често те споделят един системен потребител и един PHP процес. Ако един от тях бъде компрометиран, всички останали са изложени.

PHP2Shell прави този риск осезаем. Уязвимостите CVE-2026-109618 и CVE-2026-109619 позволяват изпълнение на злонамерен код без вход в системата, независимо от CMS. Според медийни съобщения още на 17.10.2026 е имало първи опит за атака, а пачовете последваха на 21.10. Решението е актуализацията. Дали една атака в предходния период засяга един или десет уебсайта обаче решава изолацията.

Особено при втората уязвимост се добавя още една мисъл: според проекта PHP вътрешното състояние на една заявка може да остане в worker процеса и да бъде използвано от по-късна заявка в същия worker. Отделните пулове за всеки уебсайт гарантират, че уебсайтовете така или иначе не споделят worker процеси.

## Какво постига open_basedir

С `open_basedir` определяте списък от директории. Файловите функции на PHP като `fopen`, `include` или `file_get_contents` тогава отказват достъп до всичко извън този списък. Внедрен скрипт така не може лесно да чете конфигурационните файлове на съседния уебсайт.

Границите са важни: проверката се извършва в рамките на PHP. Програми, стартирани извън PHP, не са обект на нея, а грешки в интерпретатора могат да я заобиколят. Затова `open_basedir` винаги принадлежи заедно със заключени системни функции, както е описано в наръчника [Правилно използване на disable_functions](https://phpsos.de/bg/ratgeber/disable-functions/), и преди всичко с разделяне на ниво операционна система.

## Изолация за всеки уебсайт в четири слоя

Устойчивото разделяне се гради на няколко слоя. Всеки улавя това, което предходният не постига.

| Слой | Мярка | Ефект |
|---|---|---|
| Операционна система | отделен системен потребител за всеки уебсайт | Файловете на други уебсайтове не могат да се четат |
| PHP процеси | отделен PHP-FPM пул със собствен сокет | няма общ worker, собствени настройки |
| PHP конфигурация | `open_basedir`, отделна tmp и session папка | допълнителна бариера, няма общи временни файлове |
| Данни | отделен потребител на базата данни с права само за собствената база | няма достъп до чужди данни на клиенти |

При висока нужда от защита, например при магазини с обработка на плащания или портали със здравни данни, се добавят контейнери или разделени сървъри.

## Конфигуриране на open_basedir в PHP-FPM пула

Следният пример показва пул за уебсайт със собствен потребител `seite1`. Пътищата и номера на версията адаптирайте към Вашата система.

```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
```

Последният ред веднага въвежда и преходната мярка на php.net за PHP2Shell. Тя действа само от пула, php.ini или конфигурацията на сървъра, не чрез `ini_set()` или `.user.ini`. Папките създавате с подходящи права:

```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
```

Как трябва да изглеждат правата в самата уеб директория, описва наръчникът [Права за файлове на уеб сървъра](https://phpsos.de/bg/ratgeber/dateirechte-webserver/).

## Свързване на уеб сървъра и проверка на резултата

В Nginx всеки уебсайт сочи към собствения си сокет. Така никоя заявка не попада в пула на друг уебсайт.

```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;
    }
}
```

Допълнителни указания за тази комбинация ще намерите на страницата [Защита на Nginx с PHP-FPM](https://phpsos.de/bg/server/nginx-php-fpm/). След рестарта проверете дали пуловете действително работят разделено:

```bash
sudo systemctl restart php8.3-fpm
# Всеки пул трябва да работи под собствения си потребител
ps -eo user,pid,cmd | grep "[p]hp-fpm: pool"
```

След това тествайте всички функции на уебсайта: качвания, обработка на изображения, кешове, планирани задачи. Съобщенията за грешки с указание `open_basedir restriction` в лога на грешките показват кой път още липсва. Добавяйте само пътища, които приложението действително изисква, и никога цялата файлова система.

> **Съвет:**
> Агенциите с много клиентски сайтове трябва да поддържат конфигурацията на пула като шаблон. Така всеки нов уебсайт получава разделянето автоматично, вместо да се налага по-късно да го добавяте. Основна информация за този случай има на страницата [Партньор по сигурността за агенции](https://phpsos.de/bg/branchen/agenturen-white-label/).

## Типични спънки при преминаването

Преминаването към разделени пулове е планируемо, но има няколко повтарящи се капана. Най-честият засяга споделените библиотеки: ако например фреймуърк или папка с шрифтове е извън директорията на уебсайта, този път трябва да се добави само за четене в `open_basedir`. По-добре е такива зависимости да се пренесат в самия проект.

Вторият капан са сесиите. Ако мястото за съхранение се смени, всички посетители веднъж се отписват, а текущите кошници се губят. Затова планирайте преминаването в спокоен времеви прозорец и го обявете вътрешно.

Трето, планираните задачи често се изпълняват през командния ред и така под друг потребител от уебсайта. Проверете cron задачите и опашките и ги пуснете под новия потребител на уебсайта, иначе се получават файлове с грешен собственик, които PHP по-късно не може да променя.

Накрая, всеки пул трябва да има собствени граници за процеси и памет. Уебсайт, който попада под натоварване или бива атакуван, така не може да повали и останалите.

## Как конкретно помага PHP SOS?

- Установяваме кои уебсайтове днес споделят потребители, процеси и бази данни.
- Създаваме за всеки уебсайт отделни потребители, пулове, temp папки и достъпи до базата данни, без да променяме приложенията.
- Тестваме всеки уебсайт след преминаването и отстраняваме целенасочено липсващите пътища.
- Документираме разделянето като шаблон за бъдещи проекти.

Как това се вписва в цялостна концепция, описва услугата [Заздравяване на сървъри за PHP уеб сървъри](https://phpsos.de/bg/leistungen/server-haertung/).


## Често задавани въпроси

**Достатъчно ли е open_basedir, за да се разделят уебсайтовете един от друг?**  
Не. open_basedir е допълнителна бариера в рамките на PHP, а не твърдо разделяне. Изолацията става надеждна едва с отделни системни потребители и пулове за всеки уебсайт, а при по-висока нужда от защита с контейнери или разделени сървъри.

**Защо след задаването на open_basedir качванията вече не работят?**  
Обикновено в списъка липсва папката за временни файлове. Създайте за всеки уебсайт собствена tmp папка, впишете я в open_basedir и задайте upload_tmp_dir и sys_temp_dir на тази папка.

**Може ли приложението само да отмени open_basedir?**  
Приложението може да ограничи настройката по време на изпълнение само допълнително, но не и да я облекчи. Все пак задайте open_basedir чрез php_admin_value в пула, за да е стойността еднозначно фиксирана.

**Възможна ли е изолация и при споделен хостинг?**  
Това зависи от хостинг доставчика. Много оферти разделят клиентите чрез отделни потребители и PHP процеси. Попитайте как е реализирано разделянето, особено ако няколко Ваши уебсайта са в един пакет.

## Източници

- [php.net: Съобщения за сигурност](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)
