Nagłówki jako Torby
Frameworki logujące HTTP traktują nagłówki żądań jako torbę klucz-wartość. API logowania eksponuje całą torbę. Operatory umożliają zapis nagłówków dla debugowania: gdy żądanie nie powiedzie się, nagłówki opowiadają historię. Bez wbudowanej listy zakazu. Bez filtrowania haseł w dokumentacji. Pełne nagłówki na dysk.
Często występują nagłówki zawierające informacje o tokenach:
- Authorization: Bearer eyJhbGciOiJIUzI1NiJ9... (JWT lub token OAuth)
- Cookie: session=abc123; auth=xyz789
- X-API-Key: sk-live-abc123...
- X-Auth-Token: ghp_abc123... (schemat osobistego tokena dostępu GitHub)
Te wartości autentykują żądanie. Zapisane w pliku logowym, autentykują każde żądanie.
Pipeline Hasła
Kiedy hasło zostanie zapisane w pliku logowym, nie zostanie ono utrzymane w jednym miejscu. Podróżuje:
1. Serwer HTTP zapisuje do /var/log/nginx/access.log
2. Agent przekształcania plików logów (logrotate) kopiuje do /var/log/nginx/access.log.1
3. Przesyłacz logów (Fluentd, Filebeat, Logstash) czyta i przesyła do agregatora
4. Agregator logów (Elasticsearch, Splunk, Datadog) indeksuje i przechowuje
5. Przechowywane przez 30-90 dni w ramach domyślnej polityki
Hasło istnieje jednocześnie w pięciu lokalizacjach. Anulowanie sesyjnego tokenu nie usuwa hasła z agregatora logów. Pozostaje on dostępny do wyszukiwania, eksportowania i dostępu dla osób mających dostęp do agregatora logów przez cały okres przechowywania.
Okno Wystawienia
Okno wystawienia hasła w pamięci: max(długość sesji, czas działania procesu). Sesja: godziny do dni. Proces: godziny do tygodni.
Okno wystawienia hasła w logu: max(długość sesji, okres przechowywania logów). Sesja: godziny do dni. Przechowywanie: 30-90 dni.
Hasło skradzione z pamięci wymagało, aby atakujący był obecny podczas okna sesji. Hasło skradzione z logu wymaga tylko dostępu do agregatora logów, dostępnego wstecz, przez cały okres przechowywania.
MOAD-0003 vs MOAD-0004
MOAD-0003 (Zdane w Kontekście): hasło w pamięci ucieka do nieprawidłowego obsługiwania żądań. Dostępne tylko przez okno procesu, przez pulpit zadaniowy. Ephemeral.
MOAD-0004 (Zarejestrowane Tajne): kredential na dysku przetrwa przesuwanie logów, przesyłanie logów & agregację logów. Dostępne wstecznie, dla każdego z dostępem do logów, przez 30-90 dni. Trwałe.
Różnica strukturalna: ephemeral vs persistent. Naprawa działa na różnym poziomie.
Ephemeral vs Persistent
Odróżnienie ephemeral/persistent określa powierzchnię ryzyka, warstwę naprawy & wymagania w zakresie reakcji na incydent.
Credential Denylist at the Serialization Layer
Naprawa: lista odrzuconych haseł na warstwie serializacji. Przed wartością nagłówka dotrze do wyjścia logu, sprawdź nazwę nagłówka w liście odrzuconych. Zastąp wartość [REDACTED].
CREDENTIAL_HEADERS = {
'authorization',
'cookie',
'x-api-key',
'x-auth-token',
'x-csrf-token',
'proxy-authorization',
}
def sanitize_headers(headers: dict) -> dict:
return {
k: '[REDACTED]' if k.lower() in CREDENTIAL_HEADERS else v
for k, v in headers.items()
}
Zapora na liście (denylist) należy umieścić na warstwie serializacji, a nie na warstwie zapytania o logi. Cenzurowanie zapytań o logi: stosowane po tym, jak autoryzacja dotarła do dysku; wartość oryginalna nadal istnieje, tylko jest ukryta przed wyświetleniem. Cenzurowanie warstwy serializacji: autoryzacja nigdy nie dociera do dysku. Wartość oryginalna nigdy nie wprowadza się do pliku logów, odbiornika logów ani agregatora logów.
Testowanie zapory na liście
Trzy wzory testowe:
- Pozytywny: żądanie z Authorization: Bearer token123 wywołuje wpis logowy z Authorization: [ZATRZYMANE]
- Negatywny: żądanie z Content-Type: application/json wywołuje wpis logowy z wartością niezmienioną
- Wrażliwe na wielkość liter: AUTHORIZATION: Bearer token123 również wywołuje [ZATRZYMANE] (nazwy nagłówków HTTP są niezależne od wielkości liter)
Zapora na liście wymaga utrzymania: nowe wzory nagłówków autoryzacji (na przykład niestandardowe nagłówki X-Service-Auth) wymagają dodania wyraźnego. Rozwiązanie jest strukturalne, ale nie jest samoutrzymane.
Zastosuj zapór na liście
Zespół konfiguruje format zapisu dostępu Nginx, aby zawierał wszystkie nagłówki żądania w celu zdiagnozowania incydentu produkcyjnego. Konfiguracja:
log_format debug_format '$remote_addr - $request - $http_authorization - $http_cookie';
access_log /var/log/nginx/debug.log debug_format;
Rozwiązują incydent i zamierzają usunąć konfigurację debugowania, ale zmiana nie dociera do produkcji przed kolejnego cyklu wdrożeń (7 dni później).