Krótko: Dla bezpieczeństwa php.ini liczą się przede wszystkim cztery obszary: brak komunikatów o błędach na zewnątrz, bezpieczne ciasteczka sesji, ograniczone uploady i zablokowane wartości, których aplikacje nie mogą nadpisać. Po PHP2Shell dochodzą środki przejściowe z php.net, przede wszystkim session.upload_progress.enabled=0. Bezpieczna konfiguracja nigdy jednak nie zastępuje aktualizacji.
Dlaczego php.ini znów wraca do uwagi po PHP2Shell
php.ini to centralny plik konfiguracyjny PHP. Na wielu serwerach skonfigurowano go raz i potem prawie nie ruszano. Wraz z PHP2Shell to się zmieniło: dla obu luk CVE-2026-109618 i CVE-2026-109619 php.net podaje środki przejściowe, które działają właśnie tutaj.
Same luki tkwią w interpreterze PHP. Naprawione są w PHP 8.5.12, 8.4.27, 8.3.36 i 8.2.35, opublikowanych 21.10.2026. Dobra konfiguracja mimo to pomaga na dwa sposoby: może utrudnić wykorzystanie luki i ogranicza szkody, jeśli coś jednak się przedostanie.
Wielu operatorów nie wie ponadto dokładnie, jakie ustawienia obowiązują na ich serwerze. To pierwszy krok.
Który php.ini obowiązuje na Państwa serwerze?
W zależności od trybu pracy PHP może czytać różne pliki konfiguracyjne. Wiersz poleceń, PHP-FPM i Apache z mod_php mają w Debianie i Ubuntu na przykład własne foldery w /etc/php/<version>/. Kto zmieni tylko plik CLI, nie zmieni niczego na stronie.
# Pliki konfiguracyjne wiersza poleceń
php --ini
# Konfiguracja PHP-FPM (dostosuj numer wersji)
php-fpm8.3 -i | grep -E "Loaded Configuration|Scan this dir"
# Sprawdzenie pojedynczych wartości PHP-FPM
php-fpm8.3 -i | grep -E "^(expose_php|display_errors|session.upload_progress.enabled) "
Dodatkowo wartości mogą znajdować się w puli FPM, w konfiguracji Apache, w .htaccess (tylko mod_php) lub w .user.ini (FPM i CGI). Która wersja faktycznie działa na serwerze i czy zawiera backport, wyjaśnia artykuł Jak prawidłowo sprawdzić wersję PHP i stan poprawek.
Ustawienia podstawowe dla większego bezpieczeństwa php.ini
Poniższe wartości są sensowne dla większości serwerów produkcyjnych. Przed wdrożeniem proszę sprawdzić w środowisku testowym, czy Państwa aplikacja radzi sobie ze wszystkimi wartościami.
; Brak informacji o wersji w nagłówku HTTP
expose_php = Off
; Błędy zapisywać w logu, ale nigdy nie wyświetlać w przeglądarce
display_errors = Off
display_startup_errors = Off
log_errors = On
error_log = /var/log/php/error.log
; Nie dołączać plików ze zdalnych adresów
allow_url_include = Off
; allow_url_fopen zostawić włączone tylko wtedy, gdy aplikacja tego potrzebuje
allow_url_fopen = Off
; Sesje: ściśle, tylko przez HTTPS, nieodczytywalne przez JavaScript
session.use_strict_mode = 1
session.use_only_cookies = 1
session.cookie_secure = 1
session.cookie_httponly = 1
session.cookie_samesite = Lax
; Ograniczyć czas działania i dane wejściowe
max_execution_time = 30
max_input_time = 60
max_input_vars = 1000
allow_url_fopen jest potrzebne niektórym aplikacjom do aktualizacji lub interfejsów. Proszę je wyłączać tylko po wcześniejszym sprawdzeniu. Funkcje wykonujące polecenia systemowe można dodatkowo zablokować; jak zrobić to bez skutków ubocznych, wyjaśnia poradnik Jak prawidłowo stosować disable_functions.
Środki przejściowe php.net dotyczące PHP2Shell
Jeśli nie mogą Państwo załatać od razu, php.net podaje kilka ustawień, które obniżają ryzyko. Są one wyraźnie niepełną ochroną, a jedynie pomostem do aktualizacji.
; Wyłączyć session upload progress (także ze względu na CVE-2026-115560)
session.upload_progress.enabled = 0
; Ograniczyć rozmiar żądania: 8M bez uploadów, 32M z uploadami
post_max_size = 8M
upload_max_filesize = 6M
; Tylko PHP 8.5: bez backtrace przy poważnych błędach
fatal_error_backtraces = 0
Ponadto php.net zaleca ustawić memory_limit=-1 tak, aby aplikacje nie mogły nadpisać tej wartości, a granicę pamięci wyznaczać przez kontener lub cgroup, a nie przez RLIMIT_AS czy RLIMIT_DATA. Ten środek należy do puli FPM lub konfiguracji serwera i powinien być połączony z działającym limitem cgroup. Pełne zestawienie znajdą Państwo na stronie Środki natychmiastowe, gdy nie można jeszcze załatać.
session.upload_progress.enabled=0 działa tylko z php.ini, puli FPM lub konfiguracji serwera. Ustawione przez ini_set() lub .user.ini, środek nie działa. Potem zrestartować wszystkie procesy robocze.
Blokowanie wartości przed nadpisaniem
Wiele aplikacji ustawia własne wartości, na przykład dla pamięci lub uploadów. Za pomocą php_admin_value i php_admin_flag ustalają Państwo ustawienia tak, by ani ini_set(), ani .user.ini nie mogły ich zmienić. W puli FPM wygląda to tak:
; /etc/php/8.3/fpm/pool.d/meine-seite.conf (fragment)
php_admin_flag[display_errors] = off
php_admin_flag[session.upload_progress.enabled] = off
php_admin_value[memory_limit] = -1
php_admin_value[post_max_size] = 8M
php_admin_value[upload_max_filesize] = 6M
php_admin_value[error_log] = /var/log/php/meine-seite.error.log
W Apache z mod_php obowiązuje ta sama logika z php_admin_value i php_admin_flag w konfiguracji VirtualHost. Następnie przeładować usługę i sprawdzić aktywną wartość:
sudo systemctl reload php8.3-fpm
# Czas startu procesów: czy jest późniejszy niż zmiana?
ps -eo pid,lstart,cmd | grep "[p]hp-fpm"
Reload restartuje procesy robocze PHP-FPM. Po aktualizacji PHP konieczny jest natomiast pełny restart wszystkich procesów PHP, aby w pamięci nie działał żaden stary proces. Przy kilku stronach na jednym serwerze warto ponadto utworzyć osobną pulę dla każdej strony, więcej w poradniku open_basedir i izolacja dla każdej strony.
Częste błędy i krótka lista kontrolna
Większość problemów z php.ini wynika nie z błędnych wartości, ale z wartości w niewłaściwym miejscu. Typowy jest zmieniony plik CLI, podczas gdy strona działa przez PHP-FPM. Równie często po zmianie brakuje restartu albo panel hostingowy nadpisuje własne ustawienie przy następnym zapisie.
Drugim klasykiem są widoczne komunikaty o błędach na działającej stronie. Zdradzają ścieżki, nazwy baz danych lub wersje i ułatwiają atakującym orientację. Zwłaszcza po przeprowadzce lub nowej instalacji display_errors często znów jest ustawione na On.
Te punkty proszę kontrolować po każdej zmianie i po każdej aktualizacji PHP:
- Który plik konfiguracyjny czyta tryb pracy używany przez WWW i czy zawiera on Państwa wartości?
- Czy
display_errorsiexpose_phpsą wyłączone, a log błędów zapisywalny? - Czy
session.upload_progress.enabledjest ustawione na0, przez php.ini lub pulę? - Czy rozmiary uploadów i żądań są ograniczone odpowiednio do aplikacji?
- Czy wszystkie procesy PHP działają z czasem startu późniejszym niż ostatnia zmiana?
Proszę utrwalić wynik z datą. Dzięki temu później można udowodnić, kiedy które ustawienie obowiązywało.
Jak konkretnie pomaga PHP SOS?
- Ustalamy, jaka konfiguracja jest faktycznie aktywna w danym trybie pracy.
- Wdrażamy uzgodnioną konfigurację podstawową i środki przejściowe PHP2Shell, przetestowane z Państwa aplikacją.
- Blokujemy ustawienia istotne dla bezpieczeństwa przed nadpisaniem i kontrolowanie restartujemy wszystkie procesy robocze.
- Dokumentujemy ustawienia i wynik kontroli, aby późniejsze zmiany pozostały możliwe do prześledzenia.
Jak wygląda trwałe zabezpieczenie, opisuje usługa Utwardzanie serwera dla serwerów WWW z PHP.
Częste pytania
Z którego php.ini właściwie korzysta mój serwer WWW?
Często nie jest to ten sam plik co w wierszu poleceń. PHP-FPM, Apache z mod_php i CLI mają zwykle własne foldery konfiguracji. Aktywny plik proszę więc sprawdzać przez odpowiedni tryb pracy, na przykład za pomocą php-fpm -i lub krótko umieszczonego pliku testowego.
Czy bezpieczne php.ini zastępuje aktualizację PHP?
Nie. Ustawienia zmniejszają powierzchnię ataku i utrudniają wykorzystanie luki, ale nie zamykają żadnej luki w interpreterze PHP. Także środki przejściowe php.net dotyczące PHP2Shell są wyraźnie niepełną ochroną.
Jaka jest różnica między php_value a php_admin_value?
Wartości ustawione przez php_value aplikacja może zmienić w czasie działania. Wartości ustawione przez php_admin_value w puli FPM lub w konfiguracji Apache są natomiast zablokowane dla aplikacji, także dla ini_set() i .user.ini.
Czy po zmianie php.ini trzeba zrestartować?
Tak. PHP-FPM i Apache z mod_php odczytują konfigurację tylko przy starcie. Nowe wartości obowiązują dopiero po restarcie lub przeładowaniu (reload) wszystkich dotkniętych usług.