Текуща ситуация: PHP2Shell. Две критични уязвимости в PHP (CVSS 9,2) позволяват злонамерен код без вход. Корекции от 21.10.2026 г.Какво да направите сега →

php_admin_value: заключване на настройки срещу презаписване

Настройка за сигурност помага малко, ако приложението я променя отново с един ред код. С php_admin_value и php_admin_flag фиксирате стойности за PHP-FPM и Apache задължително.

Актуалност 5 мин. четенеЗаздравяване и конфигурация

Накратко: php_admin_value и php_admin_flag задават настройки на PHP в пула на PHP-FPM или в конфигурацията на Apache така, че приложенията не могат да ги променят нито чрез ini_set(), нито чрез .htaccess. php.net изисква точно това за преходните мерки при PHP2Shell, например за memory_limit=-1. След задаването услугата трябва да се рестартира, а стойността да се провери в уеб контекст.

Защо „зададено“ не значи „заключено“

През дните след 21 октомври 2026 г. много администратори записаха преходните мерки на php.net в своя php.ini. Един детайл от препоръката често се изгуби: memory_limit=-1 трябва да е зададен така, че приложенията да не могат да го презапишат. php.net изрично посочва за това php_admin_value в пула на FPM или в конфигурацията на Apache.

Причината е проста. Много CMS, магазини и рамки задават свои собствени стойности, например по-висок лимит на паметта за импорти. Ако стойността стои само в php.ini, приложението я презаписва при следващото извикване. Защитната мярка тогава съществува на хартия, но не и в работещия процес.

Това не засяга само PHP2Shell. Всяко заздравяване, от изключени изходи на грешки до лимити за качване, е толкова силно, колкото е най-слабото му ниво.

Кой изобщо може да променя настройките на PHP

PHP познава четири режима на промяна. Всяка настройка има един от тях и той определя на кои места може да бъде зададена. Значенията идват от ръководството на PHP.

Режим Къде може да се задава стойността Примери
INI_USER в скрипта чрез ini_set() и в .user.ini малко стойности за времето на изпълнение
INI_PERDIR php.ini, .htaccess, httpd.conf, .user.ini post_max_size, session.upload_progress.enabled
INI_SYSTEM само php.ini или httpd.conf file_uploads, disable_functions
INI_ALL навсякъде, и чрез ini_set() memory_limit, display_errors, open_basedir

Опасни са най-вече стойностите INI_ALL: те могат да се променят от всеки скрипт. Стойностите INI_PERDIR наистина не могат да се променят чрез ini_set(), но могат чрез .htaccess при mod_php или .user.ini при PHP-FPM. Който има права за писане в уеб корена, тоест и внедреният код, може да създава такива файлове.

php_admin_value в пула на FPM и в Apache

При PHP-FPM стойностите стоят във файла на пула. Ръководството на PHP отбелязва: стойности, зададени с php_admin_value и php_admin_flag, не могат да се презаписват чрез ini_set(). За стойности включено-изключено ползвайте php_admin_flag, за всички останали php_admin_value.

; /etc/php/8.3/fpm/pool.d/seite1.conf (откъс)
[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/

Според php.net memory_limit=-1 принадлежи в конфигурацията само заедно с лимит на паметта чрез контейнер или cgroup. Как това се постига със systemd, е описано в статията Задаване на лимити на паметта със systemd и cgroups.

При Apache с mod_php директивите принадлежат в конфигурацията на сървъра или във VirtualHost. Според ръководството на PHP те не са позволени в .htaccess, а веднъж зададени, нито .htaccess, нито 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>

Две тънкости от ръководството: за да изтриете предишно зададена стойност, използвайте none като стойност. А константите на PHP като E_ALL нямат значение в конфигурацията на Apache; за error_reporting там трябва да посочите числовата стойност.

Кои стойности да заключите

Не всяка настройка трябва да е заключена. Смислено е това за всичко, което засяга сигурността или служи като преходна мярка:

  1. Преходните стойности на php.net за PHP2Shell: memory_limit, post_max_size, upload_max_filesize, session.upload_progress.enabled и за PHP 8.5 fatal_error_backtraces.
  2. Изход на грешки и протоколиране: display_errors, display_startup_errors, log_errors, error_log.
  3. Достъп до файлове и изолация: open_basedir, upload_tmp_dir, session.save_path.
  4. Мрежови достъпи от PHP: allow_url_include и, ако приложението не го изисква, allow_url_fopen.
  5. Блокирани функции чрез disable_functions, които в пула според ръководството допълват списъка от php.ini, а не го заместват. Подробности в ръководството Правилно използване на disable_functions.

При session.upload_progress.enabled заключването е особено важно, защото иначе стойността би могла да бъде включена отново чрез .user.ini. Повече по темата в Изключване на session.upload_progress: правилно и трайно.

Проверка дали заключването действа

След всяка промяна рестартирайте услугата и проверете стойността в уеб контекст. Кратък проверочен файл, изтрит веднага след това, показва дали пулът държи стойността, дори когато приложението иска да я промени:

<?php
// Проверочен файл: поставете го за кратко, извикайте го веднъж през домейна, изтрийте го веднага
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";

Очаква се -1 и „blockiert“. Ако изходът е „MÖGLICH“, стойността не е зададена чрез php_admin_value или услугата още не е рестартирана. Повторете проверката за всеки пул и всяка версия на PHP.

Съвет

Водете заключените стойности централно, например в шаблон на пул или във Вашето управление на конфигурацията. Хостинг панелите понякога презаписват ръчно променени файлове на пулове при следващото запазване; там стойностите принадлежат в предвидените от панела полета.

Как PHP подрежда принципно нивата на конфигурация, обяснява php.ini обяснен: структура, нива и приоритет. Пълните преходни мерки са в Незабавни мерки, когато още не можете да пачнете.

Извод: едва заключената стойност е наистина зададена

Преходните мерки на php.net за PHP2Shell изведоха на преден план едно разграничение, което преди често се пренебрегваше: стойност в php.ini е за много настройки само предложение, а стойност в php_admin_value е изискване. За удобни стойности като часовата зона разликата е без значение. За настройки на сигурността и преходни мерки тя решава дали мярката изобщо действа в работата.

Усилието е обозримо: шепа редове за всеки пул или VirtualHost, едно рестартиране, една кратка проверка. Дръжте списъка със заключени стойности малък и обоснован, за да могат разработчиците да разберат защо тяхното приложение не бива да променя дадена стойност. И поддържайте списъка във Вашите шаблони, за да го наследяват автоматично новите сайтове.

Как помага PHP SOS конкретно?

  • Прочитане на нивата: установяваме за всеки сайт кои стойности от php.ini, пула, Apache, .htaccess или .user.ini действително важат.
  • Задаване на заключвания: вписваме свързаните със сигурността стойности и преходните мерки за PHP2Shell като php_admin_value респективно php_admin_flag и рестартираме услугите.
  • Тест на приложението: проверяваме дали приложението работи безгрешно със заключените стойности и анализираме лога за грешки.
  • Поддържане на шаблоните: в рамките на заздравяването на сървъра пренасяме стойностите в шаблони на пулове и в документацията.

Често задавани въпроси

Каква е разликата между php_value и php_admin_value?

И двете задават настройка на PHP. Стойности от php_value приложението може по-късно да промени отново, например чрез ini_set() или .htaccess. Стойности от php_admin_value и php_admin_flag според ръководството на PHP са заключени за ini_set(), а при Apache и за .htaccess.

Мога ли да запиша php_admin_value във файл .htaccess?

Не. Според ръководството на PHP php_admin_value не е позволено във файлове .htaccess. То принадлежи в конфигурацията на сървъра Apache или във VirtualHost, а при PHP-FPM във файла на пула.

Какво се случва, когато приложение иска да промени заключена стойност?

Извикването на ini_set() се проваля и връща false, заключената стойност остава. Добре програмираните приложения се справят с това. След прехода все пак проверете лога за грешки и най-важните функции.

Трябва ли да рестартирам след промяна в пула?

Да. PHP-FPM чете файловете на пуловете при стартиране или при презареждане на услугата. При Apache с mod_php същото важи за конфигурацията на сървъра. Без рестартиране старата стойност продължава да работи.

Може ли disable_functions да се разшири в пула?

Да, със особеност: според ръководството на PHP disable_functions в пула на FPM не презаписва стойностите от php.ini, а ги допълва. Пулът може да блокира още функции, но не може да освободи такива.

Източници

Незабавен контакт

Всеки час има значение. Пишете ни сега.

Опишете накратко системата, версията на PHP и какво сте забелязали. Ние се свързваме с Вас, уточняваме ситуацията и работим отдалечено, докато инцидентът бъде приключен и документиран.

Незабавна помощ