Krótko: php_admin_value i php_admin_flag ustawiają opcje PHP w puli PHP-FPM lub w konfiguracji Apache tak, że aplikacje nie mogą ich zmienić ani przez ini_set(), ani przez .htaccess. Dokładnie tego wymaga php.net dla środków przejściowych PHP2Shell, na przykład dla memory_limit=-1. Po ustawieniu usługa musi zostać zrestartowana, a wartość sprawdzona w kontekście WWW.
Dlaczego „ustawione” nie znaczy „zablokowane”
W dniach po 21 października 2026 wielu administratorów wpisało środki przejściowe z php.net do swojego php.ini. Jeden szczegół zalecenia często przy tym umykał: memory_limit=-1 ma być ustawione tak, aby aplikacje nie mogły go nadpisać. php.net wymienia do tego wprost php_admin_value w puli FPM lub w konfiguracji Apache.
Powód jest prosty. Wiele systemów CMS, sklepów i frameworków ustawia własne wartości, na przykład wyższy limit pamięci dla importów. Jeśli wartość stoi tylko w php.ini, aplikacja nadpisze ją przy następnym wywołaniu. Środek ochronny istnieje wtedy na papierze, ale nie w działającym procesie.
Nie dotyczy to tylko PHP2Shell. Każde utwardzanie, od wyłączonego wyświetlania błędów po limity uploadu, jest tak silne jak jego najsłabszy poziom.
Kto w ogóle może zmieniać ustawienia PHP
PHP zna cztery tryby zmiany. Każde ustawienie ma jeden z nich i on określa, w jakich miejscach można je ustawić. Znaczenia pochodzą z podręcznika PHP.
| Tryb | Gdzie można ustawić wartość | Przykłady |
|---|---|---|
INI_USER |
w skrypcie przez ini_set() i w .user.ini |
nieliczne wartości czasu wykonania |
INI_PERDIR |
php.ini, .htaccess, httpd.conf, .user.ini |
post_max_size, session.upload_progress.enabled |
INI_SYSTEM |
tylko php.ini lub httpd.conf |
file_uploads, disable_functions |
INI_ALL |
wszędzie, także przez ini_set() |
memory_limit, display_errors, open_basedir |
Niebezpieczne są przede wszystkim wartości INI_ALL: można je zmienić z każdego skryptu. Wartości INI_PERDIR nie da się wprawdzie zmienić przez ini_set(), ale można to zrobić przez .htaccess przy mod_php lub .user.ini przy PHP-FPM. Kto ma prawa zapisu w katalogu głównym strony, a więc także wstrzyknięty kod, może takie pliki zakładać.
php_admin_value w puli FPM i w Apache
W PHP-FPM wartości stoją w pliku puli. Podręcznik PHP stwierdza: wartości ustawione przez php_admin_value i php_admin_flag nie dają się nadpisać przez ini_set(). Dla wartości włącz/wyłącz proszę użyć php_admin_flag, dla wszystkich pozostałych php_admin_value.
; /etc/php/8.3/fpm/pool.d/seite1.conf (fragment)
[seite1]
user = seite1
group = seite1
listen = /run/php/seite1.sock
php_admin_value[memory_limit] = -1
php_admin_value[post_max_size] = 32M
php_admin_value[upload_max_filesize] = 24M
php_admin_flag[session.upload_progress.enabled] = off
php_admin_flag[display_errors] = off
php_admin_value[error_log] = /var/log/php/seite1-fehler.log
php_admin_value[open_basedir] = /var/www/seite1/:/tmp/seite1/
memory_limit=-1 należy według php.net do konfiguracji tylko razem z limitem pamięci przez kontener lub cgroup. Jak to się udaje z systemd, opisuje artykuł Ustawianie limitów pamięci za pomocą systemd i cgroups.
W Apache z mod_php dyrektywy należą do konfiguracji serwera lub VirtualHost. Według podręcznika PHP nie są dozwolone w .htaccess, a raz ustawione nie może ich zmienić ani .htaccess, ani ini_set().
<VirtualHost *:443>
ServerName www.example.de
DocumentRoot /var/www/seite1/public
<IfModule php_module>
php_admin_value memory_limit -1
php_admin_value post_max_size 32M
php_admin_value upload_max_filesize 24M
php_admin_flag session.upload_progress.enabled off
php_admin_flag display_errors off
</IfModule>
</VirtualHost>
Dwa niuanse z podręcznika: aby usunąć wcześniej ustawioną wartość, należy użyć none jako wartości. A stałe PHP takie jak E_ALL nie mają w konfiguracji Apache znaczenia; dla error_reporting trzeba tam podać wartość liczbową.
Które wartości warto blokować
Nie każde ustawienie musi być zablokowane. Ma to sens dla wszystkiego, co dotyczy bezpieczeństwa lub służy jako środek przejściowy:
- Wartości przejściowe PHP2Shell z php.net:
memory_limit,post_max_size,upload_max_filesize,session.upload_progress.enabledoraz w PHP 8.5fatal_error_backtraces. - Wyświetlanie błędów i rejestrowanie:
display_errors,display_startup_errors,log_errors,error_log. - Dostęp do plików i izolacja:
open_basedir,upload_tmp_dir,session.save_path. - Dostęp sieciowy z PHP:
allow_url_includeoraz, jeśli aplikacja tego nie potrzebuje,allow_url_fopen. - Zablokowane funkcje przez
disable_functions, które w puli według podręcznika uzupełniają listę z php.ini, a nie ją zastępują. Szczegóły w poradniku Właściwe użycie disable_functions.
W przypadku session.upload_progress.enabled blokowanie jest szczególnie ważne, ponieważ wartość mogłaby inaczej zostać ponownie włączona przez .user.ini. Więcej w artykule Wyłączanie session.upload_progress: poprawnie i na stałe.
Sprawdzanie, czy blokada działa
Po każdej zmianie restartują Państwo usługę i sprawdzają wartość w kontekście WWW. Krótki, natychmiast usuwany plik testowy pokazuje, czy pula utrzymuje wartość, także gdy aplikacja chce ją zmienić:
<?php
// Plik testowy: umieścić krótko, wywołać raz przez domenę, od razu usunąć
header('Content-Type: text/plain');
$vorher = ini_get('memory_limit');
$versuch = @ini_set('memory_limit', '256M');
echo "memory_limit: $vorher\n";
echo 'Änderung per ini_set() ', ($versuch === false ? 'blockiert' : 'MÖGLICH'), "\n";
Oczekiwane są -1 i „blockiert”. Jeśli wynik brzmi „MÖGLICH”, wartość nie jest ustawiona przez php_admin_value albo usługa nie została jeszcze zrestartowana. Proszę powtórzyć sprawdzenie dla każdej puli i każdej wersji PHP.
Proszę zapisywać zablokowane wartości centralnie, na przykład w szablonie puli lub w narzędziu do zarządzania konfiguracją. Panele hostingu częściowo nadpisują ręcznie zmienione pliki puli przy następnym zapisie; tam wartości należą do pól przewidzianych przez panel.
Jak PHP porządkuje swoje poziomy konfiguracji jako całość, wyjaśnia artykuł Plik php.ini wyjaśniony: budowa, poziomy i pierwszeństwo. Pełne środki przejściowe znajdują się na stronie Środki doraźne, gdy nie mogą Państwo jeszcze załatać.
Wniosek: dopiero zablokowane jest naprawdę ustawione
Środki przejściowe php.net dla PHP2Shell uświadomiły rozróżnienie, które wcześniej często pomijano: wartość w php.ini jest dla wielu ustawień tylko propozycją, a wartość w php_admin_value wytyczną. Dla wartości wygody, takich jak strefa czasowa, różnica jest nieistotna. Dla ustawień bezpieczeństwa i środków przejściowych rozstrzyga o tym, czy środek w ogóle działa w bieżącej pracy.
Nakład jest niewielki: garść wierszy na pulę lub VirtualHost, restart, krótkie sprawdzenie. Proszę utrzymywać listę zablokowanych wartości krótką i uzasadnioną, aby programiści mogli zrozumieć, dlaczego ich aplikacja nie może zmienić danej wartości. I proszę prowadzić listę w szablonach, aby nowe strony dziedziczyły ją automatycznie.
Jak konkretnie pomaga PHP SOS?
- Odczyt poziomów: ustalamy dla każdej strony, jakie wartości z php.ini, puli, Apache,
.htaccesslub.user.inifaktycznie obowiązują. - Ustawienie blokad: wartości istotne dla bezpieczeństwa i środki przejściowe PHP2Shell wpisujemy jako
php_admin_valuelubphp_admin_flagi restartujemy usługi. - Test aplikacji: sprawdzamy, czy aplikacja działa bezbłędnie z zablokowanymi wartościami, i analizujemy log błędów.
- Utrzymanie szablonów: w ramach utwardzania serwerów przenosimy wartości do szablonów pul i dokumentacji.
Częste pytania
Jaka jest różnica między php_value a php_admin_value?
Oba ustawiają opcję PHP. Wartości z php_value aplikacja może później zmienić, na przykład przez ini_set() lub .htaccess. Wartości z php_admin_value i php_admin_flag są według podręcznika PHP zablokowane dla ini_set(), a w Apache także dla .htaccess.
Czy mogę wpisać php_admin_value do pliku .htaccess?
Nie. Według podręcznika PHP php_admin_value nie jest dozwolone w plikach .htaccess. Należy do konfiguracji serwera Apache lub VirtualHost, a przy PHP-FPM do pliku puli.
Co się dzieje, gdy aplikacja chce zmienić zablokowaną wartość?
Wywołanie ini_set() kończy się niepowodzeniem i zwraca false, zablokowana wartość pozostaje. Dobrze zaprogramowane aplikacje sobie z tym radzą. Po przestawieniu proszę mimo to sprawdzić log błędów i najważniejsze funkcje.
Czy po zmianie w puli muszę zrestartować usługę?
Tak. PHP-FPM odczytuje pliki puli przy starcie lub przeładowaniu usługi. W Apache z mod_php to samo dotyczy konfiguracji serwera. Bez restartu działa dalej stara wartość.
Czy disable_functions można rozszerzyć w puli?
Tak, z jedną osobliwością: według podręcznika PHP disable_functions w puli FPM nie nadpisuje wartości z php.ini, lecz je uzupełnia. Pula może więc zablokować kolejne funkcje, ale żadnej nie może odblokować.