Header als Beutel
HTTP-Protokollierungsframeworks behandeln Anforderungsheaders als Beutel mit Schlüssel-Wert-Paaren. Die Protokollierungs-API zeigt den vollständigen Beutel an. Betreiber aktivieren die Header-Protokollierung für Debugging: Wenn eine Anforderung fehlschlägt, erzählen die Headers die Geschichte. Keine integrierte Blockliste. Keine Anmeldeinformationen-Filterung in der Dokumentation. Vollständige Headers auf die Festplatte.
Die Anmeldeinformationen-Header in einer typischen Anforderung:
- Authorization: Bearer eyJhbGciOiJIUzI1NiJ9... (JWT oder OAuth-Token)
- Cookie: session=abc123; auth=xyz789
- X-API-Key: sk-live-abc123...
- X-Auth-Token: ghp_abc123... (GitHub persönlicher Zugriffstoken-Muster)
Diese Werte authentifizieren die Anforderung. Geschrieben in eine Logdatei, authentifizieren sie jede Anforderung.
Der Anmeldeinformationen-Pipeline
Eine Anmeldeinformation, die in eine Logdatei geschrieben wird, bleibt nicht an einem Ort. Sie reist:
1. Webserver schreibt in /var/log/nginx/access.log
2. Log-Rotation-Agent (logrotate) kopiert in /var/log/nginx/access.log.1
3. Log-Shipper (Fluentd, Filebeat, Logstash) liest & verschickt zu Aggregator
4. Log-Aggregator (Elasticsearch, Splunk, Datadog) indexiert & speichert
5. Unter Standardrichtlinie für 30-90 Tage gespeichert
Die Anmeldeinformationen existieren in allen fünf Orten gleichzeitig. Widerruf des Sitzungstokens entfernt die Anmeldeinformationen nicht aus dem Log-Aggregator. Es bleibt suchbar, exportierbar & zugänglich für Personen mit Log-Zugriff für das gesamte Retentionsfenster.
Das Expositionszeitfenster
Expositionszeitfenster für eine Anmeldeinformation im Speicher: max(Sitzungsdauer, Prozesslebensdauer). Sitzung: Stunden bis Tage. Prozess: Stunden bis Wochen.
Expositionszeitfenster für eine Anmeldeinformation in einem Log: max(Sitzungsdauer, Log-Retention). Sitzung: Stunden bis Tage. Retention: 30-90 Tage.
Eine Anmeldeinformation, die von der Speicherung gestohlen wurde, benötigte den Angreifer, um während des Sitzungszeitfensters anwesend zu sein. Eine Anmeldeinformation, die von einem Log gestohlen wurde, benötigt nur Zugriff auf den Log-Aggregator, der rückwirkend für das gesamte Retentionszeitraum verfügbar ist.
MOAD-0003 vs MOAD-0004
MOAD-0003 (Leaked Context): Eine Anmeldeinformation im Speicher gelangt zu dem falschen Anforderungs-Handler. Erreichbar nur während des Prozessfensters, über den Thread-Pool. Ephemeral.
MOAD-0004 (Gesichertes Protokoll): Eine Zugangsdaten auf der Festplatte persistieren bei der Logrotation, Logauswertung und Logaggregation. Rückerreichbar retroaktiv für Personen, die auf die Logs zugreifen können, für 30-90 Tage. Persistierend.
Die strukturelle Differenz: vorübergehend gegenüber persistierend. Der Fix wirkt auf einer anderen Ebene.
Vorübergehend gegenüber Persistierend
Die Unterscheidung zwischen vorübergehend und persistierend bestimmt die Risikofläche, die Fixebene und die Anforderungen für die Behebung von Vorfällen.
Zugriffszulassungsliste im Serialisierungsprozess
Der Fix: Eine Zugriffszulassungsliste im Serialisierungsprozess. Bevor ein Headerwert das Protokollausgang erreicht, prüfen Sie den Headernamen gegen eine Denylist. Ersetzen Sie den Wert durch [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()
}
Die Blockliste gehört in die Serialisierungsschicht und nicht in die Ebene der Protokollobjektanfragen. Protokollobjektanfragen-Zensur: wird nachdem die Anmeldeinformationen den Disk speichern; der Rohwert existiert immer noch, ist jedoch vom Display versteckt. Serialisierungsschicht-Zensur: Die Anmeldeinformationen erreichen nie den Disk. Der Rohwert tritt nie im Protokollfile, dem Protokollversender oder dem Protokollaggregator ein.
Testen der Blockliste
Drei Testmuster:
- Positiv: Eine Anfrage mit Authorization: Bearer token123 erzeugt ein Protokoll-Eintrag mit Authorization: [VERDUNKELT]
- Negativ: Eine Anfrage mit Content-Type: application/json erzeugt einen Protokolleintrag mit dem Wert unverändert
- Fallunterscheidung: AUTHORIZATION: Bearer token123 erzeugt ebenfalls [VERDUNKELT] (HTTP-Kopfnamen sind case-insensitive)
Die Blockliste erfordert Wartung: Neue Anmeldeinformationen-Kopfereignismuster (z.B. benutzerdefinierte X-Service-Auth-Kopfereignisse) benötigen eine explizite Hinzufügung. Die Lösung ist strukturiert, aber nicht selbstunterhaltsam.
Anwenden der Blockliste
Ein Team konfiguriert ihre Nginx-Zugriffsprotokollformat, um alle Anfragekopfereignisse für die Problembehebung eines Produktionsvorfalls zu include. Die Konfiguration:
log_format debug_format '$remote_addr - $request - $http_authorization - $http_cookie';
access_log /var/log/nginx/debug.log debug_format;
Sie beheben den Vorfall und beabsichtigen, die Debug-Konfiguration zu entfernen, aber die Änderung erreicht die Produktionsumgebung nicht, bevor der nächste Bereitstellungszyklus (7 Tage später) beginnt.