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

display_errors off: изключване на изхода на грешки в продукция

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

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

Накратко: На жив сайт display_errors = Off принадлежи в php.ini, заедно с display_startup_errors = Off, log_errors = On и лог за грешки извън уеб корена. Освен това CMS и рамките трябва да работят в продукционен режим, иначе собствените им страници с грешки показват подробностите. Заключени с php_admin_flag и проверявани след всяка актуализация, грешките остават в лога, а не в браузъра.

Какво издава едно-единствено съобщение за грешка

Предупреждение в горния край на страницата, „Fatal error" вместо прегледа на поръчката: такива изходи изглеждат безобидни. За атакуващия те са карта. Те показват пълни пътища до файлове, имена на бази данни и таблици, използвани библиотеки и често версията на PHP.

Особено в положения като PHP2Shell, когато масово се търсят уязвими сървъри, един сървър трябва да издава възможно най-малко за себе си. Това не затваря уязвимост в интерпретатора на PHP, но затруднява всяка следваща стъпка след пробив и прави целенасочените атаки срещу Вашето приложение по-трудни.

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

Стойностите по подразбиране не са предвидени за продукция

Мнозина предполагат, че PHP сам скрива грешките. Ръководството на PHP казва друго: вградената стойност по подразбиране на display_errors е 1, а display_startup_errors е от PHP 8.0 също включен по подразбиране. Едва доставеният шаблон php.ini-production задава и двете на Off. Ръководството изрично нарича display_errors функция за разработка, която никога не бива да се използва на системи в интернет.

Дали Вашият сървър ползва продукционния шаблон, не е очевидно. Образите на контейнери понякога стартират изцяло без php.ini, хостинг панелите задават собствени стойности, а след преместване обичайно се копира шаблонът за разработка.

display_errors off: преглед на настройките

Следните стойности са смислени за продукционни сървъри. Константи като E_ALL работят само в php.ini; в конфигурацията на Apache те според ръководството на PHP нямат значение и трябва да се задават като число.

Настройка Продукция Цел
display_errors Off без грешки в браузъра
display_startup_errors Off без грешки при стартиране на PHP в изхода
log_errors On записване на грешките в протокола
error_log път извън уеб корена собствен лог файл за всеки сайт или пул
error_reporting E_ALL протоколиране на всички грешки, без показване
html_errors Off чист текст вместо HTML в протоколите
zend.exception_ignore_args On без аргументи на функции в stack trace
fatal_error_backtraces 0 до актуализацията (само PHP 8.5) преходна мярка според php.net

zend.exception_ignore_args е особено ценна. Без тази настройка stack trace в логовете и на страниците с грешки могат да съдържат аргументите на извикванията на функции, тоест и пароли или токени, които тъкмо са се обработвали.

; php.ini на уеб SAPI
display_errors = Off
display_startup_errors = Off
log_errors = On
error_log = /var/log/php/website-fehler.log
error_reporting = E_ALL
html_errors = Off
zend.exception_ignore_args = On
; само PHP 8.5, преходна мярка до актуализацията до 8.5.12:
; fatal_error_backtraces = 0

В пула на FPM заключвате най-важните стойности допълнително, за да не ги включи отново никое приложение чрез ini_set():

; напр. /etc/php/8.3/fpm/pool.d/seite1.conf
php_admin_flag[display_errors] = off
php_admin_flag[display_startup_errors] = off
php_admin_flag[log_errors] = on
php_admin_value[error_log] = /var/log/php/seite1-fehler.log

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

Вторият превключвател: режимът за отстраняване на грешки на приложението

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

Затова проверете за всяко приложение собствения му превключвател. При WordPress това са WP_DEBUG и WP_DEBUG_DISPLAY в wp-config.php, при Laravel и Symfony APP_DEBUG и средата във файла .env, при други системи продукционният режим според документацията на производителя. На жива система режимът за отстраняване на грешки трябва да е изключен трайно, дори „само за кратко за тест" е риск.

Как грешките в приложението се обработват чисто, вместо да се потискат, описва Грешки и изключения в PHP.

Така откривате изхода на грешки, преди други да го направят

Еднократната настройка не е достатъчна. Изходът на грешки се връща след актуализации, преместване или промени в панела. Помага кратък ред на проверка:

  1. Проверете действащите стойности в уеб контекст, не само в командния ред, например с проверочен файл, поставен за кратко и изтрит веднага след това.
  2. Проверете режима за отстраняване на грешки на всяко приложение в неговия конфигурационен файл.
  3. Претърсете върнатите страници за типични текстове на грешки, както в кодовия блок по-долу.
  4. Потърсете в търсачката със заявка site: към Вашия домейн за термини като „Fatal error" или „Warning".
  5. Проверете дали лог файлът за грешки се пише и дали не е в уеб корена.
# Претърсване на върнатите страници за текстове на грешки на PHP (само собствени домейни)
for url in https://www.example.de/ https://www.example.de/kontakt/; do
  curl -s "$url" | grep -E -o "(Fatal error|Warning|Notice|Deprecated|Stack trace)[^<]{0,80}" | head -3
done
# Пише ли се лог файлът за грешки?
ls -l /var/log/php/
Важно

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

Извод: тихо в браузъра, словоохотливо в лога

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

Който изключи display_errors и display_startup_errors, заключи стойностите в пула, провери режима за отстраняване на грешки на приложението и редовно проверява резултата, затваря един от най-честите източници на ненужно разкриване на информация. Усилието е малко, ефектът трае, докато проверката остава част от всяка актуализация.

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

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

  • Проверка: прочитаме действащите настройки за грешки за всеки сайт и пул и претърсваме върнатите страници за изход на грешки.
  • Превключване: задаваме настройките на PHP и приложението за продукционна работа и ги заключваме срещу презаписване.
  • Настройка на протоколите: логовете за грешки са извън уеб корена, ротират се и са достъпни за Вашите разработчици.
  • Трайно поддържане: в договора за поддръжка на сигурността проверяваме настройките наново след всяка актуализация.

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

Не е ли display_errors в PHP така или иначе изключен?

Не автоматично. Според ръководството на PHP вградената стойност по подразбиране на display_errors е 1. Едва доставеният шаблон php.ini-production задава Off. Дали Вашият сървър ползва този шаблон, зависи от дистрибуцията, панела или образа на контейнера и трябва да се провери.

Достатъчно ли е display_errors = Off, ако WordPress или Laravel работят в режим на отстраняване на грешки?

Не. Много CMS и рамки носят собствени страници с грешки, които могат да показват подробности независимо от PHP. Затова изключете и режима за отстраняване на грешки на приложението, например WP_DEBUG_DISPLAY при WordPress или APP_DEBUG при Laravel и Symfony.

Къде отиват грешките, когато вече не се показват?

С log_errors = On PHP ги записва във файла, посочен от error_log, или в протокола на съответния режим на работа, например лога за грешки на Apache или PHP-FPM. Файлът трябва да е извън уеб корена и да се ротира редовно.

Какво общо има fatal_error_backtraces с PHP2Shell?

Настройката съществува от PHP 8.5 и е активна по подразбиране. php.net посочва fatal_error_backtraces=0 с последващо рестартиране като една от преходните мерки за PHP 8.5, докато актуализацията до 8.5.12 още предстои. Тя не замества актуализацията.

Източници

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

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

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

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