Aktualna sytuacja: PHP2Shell. Dwie krytyczne luki w PHP (CVSS 9,2) umożliwiają wykonanie złośliwego kodu bez logowania. Poprawki od 21.10.2026.Co należy teraz zrobić →

open_basedir i izolacja każdej strony

Jak za pomocą open_basedir, osobnych użytkowników systemowych i oddzielnych pul PHP-FPM zapobiec temu, by włamanie na jedną stronę dotknęło wszystkich pozostałych na serwerze.

Stan 5 min czytaniaPoradniki

Krótko: open_basedir ogranicza katalogi, do których PHP ma dostęp. Samo w sobie jest to tylko dodatkowa bariera. Skuteczna izolacja każdej strony powstaje dopiero we współdziałaniu: osobny użytkownik systemowy, osobna pula PHP-FPM, osobny folder tymczasowy i osobne dostępy do bazy danych. Wtedy włamanie na jedną stronę pozostaje ograniczone do tej strony.

Dlaczego izolacja po PHP2Shell decyduje o rozmiarze szkody

Na wielu serwerach obok siebie działa kilka stron: strona firmowa, sklep, stara strona kampanii, a w agencjach często dziesiątki projektów klientów. Często dzielą one jednego użytkownika systemowego i jeden proces PHP. Jeśli jedna z nich zostanie skompromitowana, wszystkie pozostałe są odsłonięte.

PHP2Shell czyni to ryzyko namacalnym. Luki CVE-2026-109618 i CVE-2026-109619 umożliwiają wykonanie złośliwego kodu bez logowania, niezależnie od CMS. Według doniesień medialnych pierwsza próba ataku miała miejsce już 17.10.2026, a poprawki pojawiły się 21.10. Rozwiązaniem jest aktualizacja. To, czy atak w okresie wcześniejszym dotknie jedną stronę czy dziesięć, rozstrzyga jednak izolacja.

Zwłaszcza przy drugiej luce dochodzi kolejna myśl: według projektu PHP wewnętrzny stan żądania może pozostać w procesie roboczym i zostać wykorzystany przez późniejsze żądanie w tym samym procesie. Oddzielne pule dla każdej strony sprawiają, że strony i tak nie dzielą procesów roboczych.

Co daje open_basedir

Za pomocą open_basedir ustalają Państwo listę katalogów. Funkcje plikowe PHP, takie jak fopen, include lub file_get_contents, odmawiają wtedy dostępu do wszystkiego poza tą listą. Wprowadzony skrypt nie może więc bez trudu czytać plików konfiguracyjnych sąsiedniej strony.

Granice są ważne: kontrola odbywa się wewnątrz PHP. Programy uruchamiane poza PHP jej nie podlegają, a błędy w interpreterze mogą ją obejść. Dlatego open_basedir zawsze powinno iść w parze z zablokowanymi funkcjami systemowymi, jak opisuje poradnik Jak prawidłowo stosować disable_functions, a przede wszystkim z rozdzieleniem na poziomie systemu operacyjnego.

Izolacja każdej strony w czterech warstwach

Wytrzymałe rozdzielenie opiera się na kilku warstwach. Każda przechwytuje to, czego nie robi poprzednia.

Warstwa Środek Efekt
System operacyjny osobny użytkownik systemowy dla każdej strony pliki innych stron nie są odczytywalne
Procesy PHP osobna pula PHP-FPM z własnym gniazdem brak wspólnego procesu roboczego, własne ustawienia
Konfiguracja PHP open_basedir, własny folder tmp i sesji dodatkowa bariera, brak wspólnych plików tymczasowych
Dane osobny użytkownik bazy danych z uprawnieniami tylko do własnej bazy brak dostępu do cudzych danych klientów

Przy wysokich potrzebach ochrony, na przykład w sklepach z obsługą płatności lub portalach z danymi zdrowotnymi, dochodzą kontenery lub osobne serwery.

Konfiguracja open_basedir w puli PHP-FPM

Poniższy przykład pokazuje pulę dla strony z własnym użytkownikiem seite1. Ścieżki i numer wersji proszę dostosować do swojego systemu.

; /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

Ostatni wiersz od razu ustawia środek przejściowy PHP2Shell z php.net. Działa on tylko z puli, php.ini lub konfiguracji serwera, a nie przez ini_set() ani .user.ini. Foldery proszę utworzyć z odpowiednimi uprawnieniami:

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

Jak powinny wyglądać uprawnienia w samym katalogu WWW, opisuje poradnik Uprawnienia do plików na serwerze WWW.

Podłączenie serwera WWW i sprawdzenie wyniku

W Nginx każda strona wskazuje na swoje własne gniazdo. Dzięki temu żadne żądanie nie trafia do puli innej strony.

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;
    }
}

Dalsze wskazówki dotyczące tego połączenia znajdą Państwo na stronie Zabezpieczanie Nginx z PHP-FPM. Po restarcie sprawdzają Państwo, czy pule rzeczywiście działają oddzielnie:

sudo systemctl restart php8.3-fpm
# Każda pula powinna działać pod własnym użytkownikiem
ps -eo user,pid,cmd | grep "[p]hp-fpm: pool"

Następnie proszę przetestować wszystkie funkcje strony: uploady, przetwarzanie obrazów, pamięci podręczne, zaplanowane zadania. Komunikaty o błędach z wzmianką o open_basedir restriction w logu błędów pokazują, której ścieżki jeszcze brakuje. Proszę dodawać tylko ścieżki, których aplikacja naprawdę potrzebuje, i nigdy całego systemu plików.

Wskazówka

Agencje z wieloma stronami klientów powinny utrzymywać konfigurację puli jako szablon. Dzięki temu każda nowa strona automatycznie otrzymuje rozdzielenie zamiast konieczności dozbrajania go później. Tło dla tego przypadku znajdą Państwo na stronie Partner bezpieczeństwa dla agencji.

Typowe pułapki przy przejściu

Przejście na oddzielne pule jest planowalne, ale ma kilka powtarzających się pułapek. Najczęstsza dotyczy współdzielonych bibliotek: jeśli na przykład framework lub folder z czcionkami leży poza katalogiem strony, ścieżkę tę trzeba dodać do open_basedir z dostępem do odczytu. Lepiej przenieść takie zależności do samego projektu.

Drugą pułapką są sesje. Jeśli zmienia się miejsce zapisu, wszyscy odwiedzający są raz wylogowani, a trwające koszyki przepadają. Przejście proszę więc zaplanować w spokojnym oknie czasowym i zapowiedzieć je wewnętrznie.

Po trzecie, zaplanowane zadania często działają przez wiersz poleceń, a tym samym pod innym użytkownikiem niż strona. Proszę sprawdzić zadania cron i kolejki i uruchamiać je pod nowym użytkownikiem strony, w przeciwnym razie powstaną pliki z niewłaściwym właścicielem, których PHP później nie będzie mógł zmieniać.

Wreszcie każda pula powinna mieć własne limity procesów i pamięci. Strona, która znajdzie się pod obciążeniem lub zostanie zaatakowana, nie może wtedy rzucić na kolana pozostałych.

Jak konkretnie pomaga PHP SOS?

  • Ustalamy, które strony dzielą dziś użytkowników, procesy i bazy danych.
  • Zakładamy dla każdej strony własnych użytkowników, pule, foldery tymczasowe i dostępy do bazy danych, bez zmiany aplikacji.
  • Testujemy każdą stronę po przejściu i celowo usuwamy brakujące ścieżki.
  • Dokumentujemy rozdzielenie jako szablon dla przyszłych projektów.

Jak to wpisuje się w całościową koncepcję, opisuje usługa Utwardzanie serwera dla serwerów WWW z PHP.

Częste pytania

Czy open_basedir wystarczy, by rozdzielić strony?

Nie. open_basedir to dodatkowa bariera wewnątrz PHP, a nie twarde rozdzielenie. Izolacja staje się niezawodna dopiero dzięki osobnym użytkownikom systemowym i pulom dla każdej strony, a przy wyższych potrzebach ochrony dzięki kontenerom lub osobnym serwerom.

Dlaczego po ustawieniu open_basedir uploady przestały działać?

Najczęściej na liście brakuje folderu plików tymczasowych. Proszę utworzyć dla każdej strony własny folder tmp, wpisać go do open_basedir i ustawić upload_tmp_dir oraz sys_temp_dir na ten folder.

Czy aplikacja może sama zniesić open_basedir?

Aplikacja może w czasie działania ustawienie tylko dalej ograniczyć, a nie złagodzić. Mimo to proszę ustawić open_basedir przez php_admin_value w puli, aby wartość była jednoznacznie ustalona.

Czy izolacja jest możliwa także na shared hostingu?

To zależy od dostawcy hostingu. Wiele ofert rozdziela klientów przez osobnych użytkowników i procesy PHP. Proszę zapytać, jak rozdzielenie jest zrealizowane, zwłaszcza jeśli kilka Państwa stron znajduje się w jednym pakiecie.

Źródła

Kontakt natychmiast

Liczy się każda godzina. Proszę napisać do nas teraz.

Proszę krótko opisać system, wersję PHP i obserwacje. Skontaktujemy się z Państwem, ustalimy sytuację i będziemy pracować zdalnie, aż incydent zostanie zamknięty i udokumentowany.

Natychmiastowa pomoc