Krótko: Logowanie w PHP z uwzględnieniem ochrony danych oznacza: zdarzenia istotne dla bezpieczeństwa rejestrować w pełni, ale haseł, tokenów, identyfikatorów sesji i wrażliwych danych klientów nigdy nie zapisywać w logu. Błędy należą do dziennika, a nie na ekran, logi leżą poza webroot i są chronione przed zmianą. To, jak długo logi są przechowywane, ustalasz świadomie wspólnie z inspektorem ochrony danych.
Między zabezpieczaniem śladów a wyciekiem danych
Po PHP2Shell media branżowe radziły przechowywać logi serwera WWW od 20.10.2026. Kto chciał to wdrożyć, często stwierdzał jedno z dwojga. Albo logi dawno zostały zrotowane i usunięte. Albo zawierały rzeczy, których tam nigdy nie powinno być: pełne dane z formularzy, hasła z nieudanych logowań, klucze API w adresach URL.
Oba przypadki są problemem. Bez logów incydentu prawie nie da się zrekonstruować. Z nadmierną zawartością sam log staje się celem, bo kto uzyska dostęp do serwera, chętnie go przeczyta. Dobre logowanie leży pomiędzy: dość na poszukiwanie śladów, jak najmniej danych wymagających ochrony.
Co aplikacja PHP powinna rejestrować
Ściągawka OWASP o logowaniu wymienia zdarzenia ważne dla bezpieczeństwa i możliwości prześledzenia. Dla typowych aplikacji PHP można je podsumować tak:
| Do logu | Nie do logu |
|---|---|
| udane i nieudane logowania | hasła, także błędnie wpisane |
| nieudane kontrole uprawnień | identyfikatory sesji jawnym tekstem |
| zmiany kont i uprawnień | tokeny dostępu i klucze API |
| błędy kontroli danych wejściowych | dane dostępowe do bazy danych |
| uploady, importy i eksporty | dane płatnicze i bankowe |
| zmiany konfiguracji, start i zatrzymanie | dane zdrowotne i inne dane szczególnie wymagające ochrony |
| błędy czasu wykonania z miejscem, bez danych użytkowych | pełna zawartość formularzy |
Każdy wpis powinien odpowiadać na pytania kiedy, gdzie, kto i co: znacznik czasu, aplikacja i host, adres źródłowy, identyfikator użytkownika, rodzaj zdarzenia i wynik. Imiona lub adresy e-mail można często zamaskować albo zastąpić wewnętrznym identyfikatorem, bez utraty użyteczności.
Dwa źródła niechcianych danych w logu są często pomijane. Pierwsze to adresy URL: jeśli token, klucz resetu hasła lub adres e-mail znajdują się w query stringu, trafiają automatycznie do logu dostępu serwera WWW, do logów proxy i do historii przeglądarki. Takie wartości należą do ciała żądania lub nagłówka, a nie do adresu. Drugie źródło to tryb debugowania. Frameworki i wtyczki w trybie debugowania często zapisują pełne żądania, zapytania do bazy danych i zmienne środowiskowe. Jeśli ten tryb pozostanie aktywny po szukaniu błędów, niepostrzeżenie rośnie plik z dokładnie tymi informacjami, których szuka atakujący. Sprawdzaj po każdym szukaniu błędów, czy wyjście debugowania zostało ponownie wyłączone, i usuwaj powstałe przy tym pliki.
Logowanie w PHP: ustawienia podstawowe
Pierwszym poziomem jest samo PHP. W produkcji błędy mają być rejestrowane, ale nie wyświetlane. Log leży poza webroot, aby nie można go było pobrać przez adres URL.
; php.ini lub pula FPM dla produkcji
display_errors = Off
display_startup_errors = Off
log_errors = On
error_log = /var/log/php/app-error.log
Dlaczego widoczne błędy są niebezpieczne, opisuje artykuł Wyłączanie wyświetlania błędów w produkcji. Jak błędy i wyjątki w PHP są ze sobą powiązane, wyjaśnia artykuł Błędy i wyjątki w PHP.
Drugim poziomem jest aplikacja. Wiele frameworków używa do tego biblioteki zgodnej ze standardem PSR-3 organizacji PHP-FIG, który ustala jednolity interfejs loggera. Ważna jest nie biblioteka, lecz dyscyplina: dane kontekstowe wybierać świadomie, zamiast zapisywać do logu całe żądania lub obiekty.
<?php
// Dane wejściowe przed zalogowaniem zneutralizować i zamaskować
function logSicher(string $text): string {
return mb_substr(str_replace(["\r", "\n"], ' ', $text), 0, 200);
}
function maskiereMail(string $mail): string {
[$name, $domain] = array_pad(explode('@', $mail, 2), 2, '');
return mb_substr($name, 0, 1) . '***@' . $domain;
}
$logger->warning('Anmeldung fehlgeschlagen', [
'benutzer' => maskiereMail(logSicher($_POST['email'] ?? '')),
'ip' => $_SERVER['REMOTE_ADDR'] ?? '',
// nigdy: 'passwort' => $_POST['passwort']
]);
Log injection i zmanipulowane wpisy
Jeśli aplikacja zapisuje dane wejściowe do logu bez filtrowania, atakujący może za pomocą znaków końca wiersza tworzyć fałszywe wpisy. Myli to analizę i może zacierać ślady. Ściągawka OWASP zaleca formaty ustrukturyzowane, takie jak JSON, usuwanie lub kodowanie znaków końca wiersza i ograniczenie długości danych wejściowych w logu.
Równie ważna jest ochrona samych logów:
- Przechowywanie poza webroot i z uprawnieniami, których użytkownik serwera WWW potrzebuje do zapisu, ale nie do usuwania starych plików.
- Kopia na drugim systemie, na przykład przez syslog po szyfrowanym połączeniu. Kto przejmie serwer, nie powinien móc po prostu usunąć śladów.
- Ograniczyć dostęp do odczytu i samemu go rejestrować. Logi prawie zawsze zawierają dane osobowe.
- Rozpoznawać awarię: Jeśli log nagle pozostaje pusty, jest to sygnał ostrzegawczy.
- Uzgodnić czas: Wszystkie serwery pobierają czas z tego samego źródła i zapisują w logu jednoznaczną strefę czasową. W przeciwnym razie wpisy serwera WWW, PHP i bazy danych prawie nie dają się po incydencie złożyć w oś czasu.
Log, który leży tylko na skompromitowanym serwerze, jako dowód jest słaby. Bieżąca kopia na oddzielnym systemie jest po incydencie często jedynym wiarygodnym źródłem.
Świadomie zdecydować o przechowywaniu i ochronie danych
To, jak długo logi mogą i muszą być przechowywane, jest wyważeniem interesu bezpieczeństwa, minimalizacji danych i wymogów ustawowych lub umownych. Art. 32 RODO wymaga środków technicznych i organizacyjnych odpowiednich do ryzyka, między innymi w celu trwałego zapewnienia poufności, integralności i dostępności systemów; rejestrowanie zdarzeń może do tego przyczyniać się. Jednocześnie danych osobowych nie wolno przechowywać dłużej, niż to konieczne.
Ustal więc termin dla każdego rodzaju logu, zapisz uzasadnienie i uzgodnij oba z inspektorem ochrony danych. W trwającym postępowaniu wyjaśniającym może być konieczne zabezpieczenie logów ponad normalny termin. Należy to wtedy również udokumentować. Ta strona jest informacją ogólną, a nie poradą prawną; przy konkretnych pytaniach pomagają inspektor ochrony danych i prawnik. Jak analizować logi po ataku, pokazuje artykuł Analiza logów serwera WWW po ataku.
Jak konkretnie pomaga PHP SOS?
- Sprawdzamy Państwa istniejące logi pod kątem haseł, tokenów i innych danych, które tam nie należą.
- Ustawiamy PHP i aplikację tak, aby błędy były rejestrowane, ale nie wyświetlane.
- Wdrażamy chronioną kopię logów na oddzielnym systemie.
- Za pośrednictwem monitoringu bezpieczeństwa na bieżąco analizujemy wpisy istotne dla bezpieczeństwa i zrozumiale zgłaszamy to, co zwraca uwagę.
Podsumowanie: Dobre logi są oszczędne w treści i hojne w ochronie. Kto dziś ustali, co jest rejestrowane, a co nigdy, ma w razie potrzeby użyteczne ślady i nie ma dodatkowego wycieku danych.
Częste pytania
Czy adresy IP mogą znajdować się w plikach logów?
Adresy IP mogą być danymi osobowymi. To, czy i jak długo je Państwo przechowują, zależy od celu i podstawy prawnej. Zakres i okres przechowywania należy ustalić z inspektorem ochrony danych; ta strona nie jest poradą prawną.
Jak długo przechowywać logi?
Tak długo, jak jest to potrzebne dla bezpieczeństwa i szukania błędów oraz dopuszczalne prawnie, i nie dłużej. Po PHP2Shell prasa branżowa zalecała przechowywanie logów serwera WWW od 20.10.2026. Terminy należy ustalić świadomie i udokumentować.
Czym jest log injection?
Jeśli dane wejściowe zawierają znaki końca wiersza lub znaki sterujące i zostaną zapisane do logu bez filtrowania, mogą tworzyć fałszywe wpisy. Zniekształca to analizy. Zapobiegają temu formaty ustrukturyzowane, takie jak JSON, i usuwanie znaków końca wiersza.
Czy display_errors w produkcji ma być wyłączone?
Tak. Błędy mają trafiać do logu, a nie do wyjścia widocznego dla odwiedzających. Widoczne komunikaty o błędach zdradzają ścieżki, zapytania, a czasem dane dostępowe.