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ć →

display_errors off: wyłączanie komunikatów błędów w produkcji

Widoczne komunikaty błędów PHP zdradzają ścieżki, nazwy baz danych i wersje. Jak wyłączyć je w PHP, we frameworku i w serwerze WWW, nie tracąc błędów z oczu.

Stan 5 min czytaniaUtwardzanie i konfiguracja

Krótko: Na działającej stronie display_errors = Off należy do php.ini, razem z display_startup_errors = Off, log_errors = On i logiem błędów poza katalogiem głównym strony. Dodatkowo systemy CMS i frameworki muszą działać w trybie produkcyjnym, w przeciwnym razie ich własne strony błędów pokazują szczegóły. Zablokowane przez php_admin_flag i sprawdzane po każdej aktualizacji, błędy zostają w logu, a nie w przeglądarce.

Co zdradza pojedynczy komunikat błędu

Ostrzeżenie na górze strony, „Fatal error” zamiast podsumowania zamówienia: takie wyświetlenia wyglądają niewinnie. Dla atakującego są mapą. Pokazują pełne ścieżki plików, nazwy baz danych i tabel, używane biblioteki, a często także wersję PHP.

Właśnie w sytuacjach takich jak PHP2Shell, gdy masowo szuka się podatnych serwerów, serwer powinien zdradzać o sobie jak najmniej. Nie zamyka to luki w interpreterze PHP, ale utrudnia każdy kolejny krok po włamaniu i czyni celowane ataki na Państwa aplikację mozolniejszymi.

Dochodzi ochrona danych. Komunikaty błędów mogą zawierać fragmenty żądań, na przykład adresy e-mail z formularzy. To, co pojawia się w przeglądarce odwiedzającego, nie jest już pod Państwa kontrolą.

Wartości domyślne nie są przeznaczone do produkcji

Wielu zakłada, że PHP samo ukrywa błędy. Podręcznik PHP mówi coś innego: wbudowana wartość domyślna display_errors to 1, a display_startup_errors jest od PHP 8.0 również domyślnie włączone. Dopiero dołączony szablon php.ini-production ustawia oba na Off. Podręcznik wyraźnie nazywa display_errors funkcją deweloperską, której nigdy nie należy używać w systemach dostępnych w internecie.

To, czy Państwa serwer używa szablonu produkcyjnego, nie jest oczywiste. Obrazy kontenerów startują częściowo w ogóle bez php.ini, panele hostingu ustawiają własne wartości, a po przeprowadzce chętnie kopiuje się szablon deweloperski.

display_errors off: ustawienia w skrócie

Poniższe wartości są sensowne dla serwerów produkcyjnych. Stałe takie jak E_ALL działają tylko w php.ini; w konfiguracji Apache nie mają według podręcznika PHP znaczenia i trzeba podawać je jako liczbę.

Ustawienie Produkcja Cel
display_errors Off brak błędów w przeglądarce
display_startup_errors Off brak błędów przy starcie PHP w wyjściu
log_errors On zapisywanie błędów do dziennika
error_log ścieżka poza katalogiem głównym strony osobny plik logu dla każdej strony lub puli
error_reporting E_ALL rejestrować wszystkie błędy, nie wyświetlać
html_errors Off zwykły tekst zamiast HTML w dziennikach
zend.exception_ignore_args On brak argumentów funkcji w śladach stosu
fatal_error_backtraces 0 do aktualizacji (tylko PHP 8.5) środek przejściowy według php.net

zend.exception_ignore_args jest szczególnie cenne. Bez tego ustawienia ślady stosu w logach i na stronach błędów mogą zawierać argumenty wywołań funkcji, a więc także hasła lub tokeny, które właśnie były przetwarzane.

; php.ini SAPI WWW
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
; tylko PHP 8.5, środek przejściowy do aktualizacji do 8.5.12:
; fatal_error_backtraces = 0

W puli FPM najważniejsze wartości blokuje się dodatkowo, aby żadna aplikacja nie włączyła ich ponownie przez ini_set():

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

Następnie zrestartować odpowiednią usługę PHP. Jak dokładnie działa blokowanie, wyjaśnia artykuł php_admin_value: blokowanie ustawień przed nadpisaniem. Pełną konfigurację podstawową znajdą Państwo w artykule Bezpieczna konfiguracja php.ini.

Drugi przełącznik: tryb debugowania aplikacji

PHP to tylko połowa sprawy. Nowoczesne frameworki same przechwytują błędy i pokazują własne, często bardzo szczegółowe strony błędów. W trybie debugowania zawierają fragmenty kodu źródłowego, wartości konfiguracji, a czasem zmienne środowiskowe. Strony te pojawiają się nawet wtedy, gdy display_errors w PHP jest wyłączone.

Dlatego proszę sprawdzić dla każdej aplikacji jej własny przełącznik. W WordPress są to WP_DEBUG i WP_DEBUG_DISPLAY w wp-config.php, w Laravel i Symfony APP_DEBUG oraz środowisko w pliku .env, w innych systemach tryb produkcyjny według dokumentacji producenta. W systemie produkcyjnym tryb debugowania ma być wyłączony na stałe, także „tylko na chwilę dla testu” jest ryzykiem.

Jak w aplikacji poprawnie obsługiwać błędy, zamiast je tłumić, opisuje artykuł Błędy i wyjątki w PHP.

Jak znaleźć wyświetlane błędy, zanim zrobią to inni

Jednorazowe ustawienie nie wystarczy. Wyświetlanie błędów wraca po aktualizacjach, przeprowadzkach lub zmianach w panelu. Pomaga krótki przebieg kontrolny:

  1. Sprawdzić obowiązujące wartości w kontekście WWW, nie tylko w wierszu poleceń, na przykład krótko umieszczonym i zaraz usuniętym plikiem testowym.
  2. Skontrolować tryb debugowania każdej aplikacji w jej pliku konfiguracyjnym.
  3. Przeszukać dostarczane strony pod kątem typowych tekstów błędów, jak w bloku kodu poniżej.
  4. W wyszukiwarce zapytaniem site: na Państwa domenę szukać pojęć takich jak „Fatal error” lub „Warning”.
  5. Sprawdzić, czy log błędów jest zapisywany i czy nie leży w katalogu głównym strony.
# Przeszukać dostarczane strony pod kątem tekstów błędów PHP (tylko własne domeny)
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
# Czy log błędów jest zapisywany?
ls -l /var/log/php/
Ważne

Ukrywanie błędów nie zastępuje ich naprawiania. Log pełen ostrzeżeń to wskazówka, że potrzebna jest konserwacja, a po włamaniu jest często ważnym śladem. Co przy tym rejestrować, a czego nie, opisuje artykuł Bezpieczne logowanie: rejestrowanie błędów bez wycieku danych.

Wniosek: cicho w przeglądarce, wylewnie w logu

Zasada dla serwerów produkcyjnych jest prosta: błędy należą do dziennika, a nie na stronę. W praktyce przeszkadzają jej wartości domyślne nieprzeznaczone do produkcji, przełączniki debugowania w aplikacjach i konfiguracje, które po aktualizacjach lub przeprowadzkach wracają do stanu pierwotnego.

Kto wyłącza display_errors i display_startup_errors, blokuje wartości w puli, kontroluje tryb debugowania aplikacji i regularnie sprawdza wynik, zamyka jedno z najczęstszych źródeł niepotrzebnego ujawniania informacji. Nakład jest niewielki, a efekt trwa, dopóki kontrola pozostaje częścią każdej aktualizacji.

Jednego nie należy przeoczyć: log błędów nie jest koszem na śmieci. Kto go regularnie czyta, rozpoznaje błędne aktualizacje, przestarzałe funkcje, a czasem także pierwsze ślady ataku, na długo zanim klienci cokolwiek zauważą.

Jak konkretnie pomaga PHP SOS?

  • Sprawdzenie: odczytujemy obowiązujące ustawienia błędów dla każdej strony i puli oraz przeszukujemy dostarczane strony pod kątem wyświetlanych błędów.
  • Przestawienie: ustawiamy PHP i aplikacje na tryb produkcyjny i blokujemy je przed nadpisaniem.
  • Konfiguracja dzienników: logi błędów leżą poza katalogiem głównym strony, są rotowane i dostępne dla Państwa programistów.
  • Utrzymanie na stałe: w ramach umowy serwisowej bezpieczeństwa po każdej aktualizacji sprawdzamy ustawienia ponownie.

Częste pytania

Czy display_errors w PHP nie jest i tak wyłączone?

Nie automatycznie. Według podręcznika PHP wbudowana wartość domyślna display_errors to 1. Dopiero dołączony szablon php.ini-production ustawia Off. To, czy Państwa serwer używa tego szablonu, zależy od dystrybucji, panelu lub obrazu kontenera i należy to sprawdzić.

Czy display_errors = Off wystarczy, gdy WordPress lub Laravel działają w trybie debugowania?

Nie. Wiele systemów CMS i frameworków ma własne strony błędów, które niezależnie od PHP mogą wyświetlać szczegóły. Dlatego należy też wyłączyć tryb debugowania aplikacji, na przykład WP_DEBUG_DISPLAY w WordPress lub APP_DEBUG w Laravel i Symfony.

Dokąd trafiają błędy, gdy nie są już wyświetlane?

Przy log_errors = On PHP zapisuje je do pliku wskazanego przez error_log lub do dziennika danego trybu pracy, na przykład logu błędów Apache lub PHP-FPM. Plik powinien leżeć poza katalogiem głównym strony i być regularnie rotowany.

Co fatal_error_backtraces ma wspólnego z PHP2Shell?

Ustawienie istnieje od PHP 8.5 i jest domyślnie aktywne. php.net podaje fatal_error_backtraces=0 z następującym po tym restartem jako jeden ze środków przejściowych dla PHP 8.5, dopóki aktualizacja do 8.5.12 jest jeszcze w toku. Nie zastępuje aktualizacji.

Ź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