Log-Hygiene: Warum schlechte Logs schlimmer sind als keine Logs
Einleitung
Schlechte Logs sind gefährlicher als keine Logs. Das klingt kontraintuitiv – aber wer glaubt, ausreichend zu loggen, und tatsächlich unzuverlässige, inkonsistente oder unvollständige Logs hat, entscheidet in einem Incident falsch. Vertrau mir, sagt der Log: 2023-01-32T25:00:00 – das war kein Angriff. In diesem Artikel zeige ich die häufigsten Log-Qualitätsprobleme, warum sie eure Detection und Forensik kaputtmachen, und wie ihr sie systematisch behebt – ohne den Log-Stack neu zu bauen.
Warum das Thema wichtig ist
Ein SIEM ist nur so gut wie die Logs, die hineingehen. Schlechte Logs erzeugen drei Probleme gleichzeitig:
- False Negatives: Angriffe werden nicht erkannt, weil die Events fehlen, falsch formatiert sind oder zum falschen Zeitpunkt stehen
- False Positives: Rules matchen auf Rauschen und produzieren Alert-Fatigue
- Forensik-Blindheit: Incident Timeline lässt sich nicht rekonstruieren, weil Timestamps inkonsistent oder Events unvollständig sind
Mandiant-Reports beschreiben regelmäßig Fälle, in denen ein Incident nur deshalb so lange unentdeckt blieb, weil entscheidende Events zwar geloggt, aber nicht auswertbar waren: falsche Zeitzone, truncated Nachrichten, fehlende Felder. Logging-Hygiene ist kein Komfort-Feature – es ist eine Detection-Voraussetzung.
Die sieben häufigsten Log-Qualitätsprobleme
1 – Timestamps ohne Zeitzone
# Schlechtes Beispiel
May 3 14:22:11 webserver sshd[1234]: Accepted publickey
# Gutes Beispiel
2026-05-03T14:22:11.453+02:00 webserver sshd[1234]: Accepted publickey
Logs ohne explizite Zeitzone sind wertlos in einem Multi-Zone-Umfeld. UTC-Offset oder explizit UTC ist Pflicht. Korrelation zwischen zwei Systemen in verschiedenen Zeitzonen ohne explizite Zone ist Raten.
Fix: Alle Log-Quellen auf UTC-Ausgabe konfigurieren. In rsyslog:
$ActionFileDefaultTemplate RSYSLOG_SyslogProtocol23Format
In journald (/etc/systemd/journald.conf):
TimeStampFormat=realtime
2 – Timestamps ohne Millisekunden
Für High-Volume-Events (Network, Endpoint, Auth) reichen Sekundenauflösung nicht. Zwei Events in derselben Sekunde können nicht kausal geordnet werden.
Fix: Syslog-Protokoll RFC 5424 verwendet ISO 8601 mit Millisekunden. Anwendungen, die nur Sekunden ausgeben: entweder in der Anwendung konfigurieren oder per Vector-Transform ergänzen:
[transforms.add_ms_timestamp]
type = "remap"
inputs = ["source"]
source = '''
.timestamp = now()
'''
3 – Inkonsistente Feldnamen
# Quelle A
{"src_ip": "10.0.1.5", "user": "admin"}
# Quelle B
{"source_address": "10.0.1.22", "username": "root"}
# Quelle C
{"RemoteAddress": "10.0.1.99", "Actor": "SYSTEM"}
Drei Quellen, drei Feldnamen für dasselbe Konzept. Eine SIEM-Rule, die auf src_ip sucht, findet Quelle A, aber nicht B und C.
Fix: Normalisierung auf ein einheitliches Schema. Empfehlung: Elastic Common Schema (ECS) oder OpenTelemetry Semantic Conventions. Normalisierungs-Mapping in Vector oder Logstash einmalig definieren:
# Vector: ECS-Normalisierung für Auth-Events
[transforms.normalize_auth]
type = "remap"
inputs = ["auth_source"]
source = '''
.source.ip = del(.src_ip) ?? del(.source_address) ?? del(.RemoteAddress)
.user.name = del(.user) ?? del(.username) ?? del(.Actor)
.@timestamp = .timestamp
'''
4 – Truncated Messages
Syslog hat traditionell ein 1024-Byte-Limit (RFC 3164). Lange Stack-Traces, SQL-Queries oder Audit-Events werden am Ende abgeschnitten – exakt der Teil, der oft am relevantesten ist.
Fix: RFC 5424 (Syslog-Protokoll 23) hat kein Größenlimit. rsyslog-Konfiguration:
$MaxMessageSize 64k
Alternativ: direktes Logging in JSON ohne Syslog-Wrapper.
5 – Fehlende Correlation-IDs
Wenn eine HTTP-Anfrage durch Load Balancer → App-Server → Datenbank geht und ein Fehler auftritt, willst du alle zugehörigen Log-Einträge finden. Ohne Correlation-ID (Request-ID, Session-ID, Trace-ID) musst du nach Zeitstempeln und IP-Adressen suchen – fehleranfällig.
Fix: Request-ID am Eingang vergeben, durch alle Komponenten weiterreichen, in jeden Log-Entry schreiben. In nginx:
log_format combined_with_id '$remote_addr - $request_id - [$time_iso8601] '
'"$request" $status $body_bytes_sent';
proxy_set_header X-Request-ID $request_id;
6 – Logs auf dem kompromittierten System
Wenn der Angreifer auf einem Host Admin-Rechte hat, löscht er die lokalen Logs – und deine Forensik beginnt mit einer leeren Datei. Logs, die nur lokal gespeichert werden, sind bei einem Incident oft bereits weg.
Fix: Forwarding in Echtzeit. Syslog-Forwarding, Wazuh-Agent, Filebeat, NXLog – alles besser als nur lokal. Logs müssen spätestens Sekunden nach dem Event auf einem anderen System sein.
7 – Zu viel oder zu wenig loggen
Zu wenig: relevante Events fehlen. Zu viel: Rauschen überwältigt die Analyse, Retention-Kosten explodieren, Detection-Rules produzieren zu viele False Positives.
Das klassische Beispiel für zu viel: DEBUG-Level-Logs im Production-SIEM. Ein nginx-Access-Log mit jedem Byte jedes CSS-Requests ist kein Security-Log.
Fix: Log-Level-Policy pro Quelle. Security-relevante Events auf INFO oder höher, Debug nur in temporären Troubleshooting-Phasen, nie in SIEM einspeisen.
Log-Qualitäts-Checkliste pro Event
Jeder Security-relevante Log-Event sollte haben:
| Feld | Beispiel | Pflicht |
|---|---|---|
| Timestamp (ISO 8601, UTC) | 2026-05-03T14:22:11.453Z |
ja |
| Hostname | webserver01.example.com |
ja |
| Log-Quelle | sshd[1234] |
ja |
| Event-Typ | authentication.success |
ja |
| User | admin |
ja |
| Quell-IP | 10.0.1.5 |
ja |
| Ziel | webserver01:22 |
je nach Event |
| Outcome | success / failure |
ja |
| Correlation-ID | req-abc-123 |
für HTTP/App-Logs |
Hygiene-Audit: So findest du Probleme schnell
Timestamp-Audit
# Alle Logs der letzten Stunde ohne erkennbare Zeitzone
journalctl --since "1 hour ago" -o json | \
jq 'select(.__REALTIME_TIMESTAMP == null or .__REALTIME_TIMESTAMP == "") | ._SYSTEMD_UNIT'
# Logs mit Timestamps in falscher Zeitzone (nicht UTC)
grep -rE '[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}[+-][0-9]{2}' /var/log/ | head -20
Feldnamen-Inkonsistenz in Elasticsearch / OpenSearch
GET /logs-*/_mapping?filter_path=**.properties.src_ip,**.properties.source.ip,**.properties.RemoteAddress
Wenn alle drei Felder existieren, hast du ein Normalisierungsproblem.
Truncation-Check
# Syslog-Einträge nahe am Limit (> 900 Bytes)
awk 'length($0) > 900' /var/log/syslog | head -5
Retention-Hygiene: das vergessene Kapitel
Log-Hygiene betrifft nicht nur Format, sondern auch Lebensdauer:
| Log-Typ | Empfehlung Retention |
|---|---|
| Security Events (Auth, Firewall, Endpoint) | 12 Monate online, 7 Jahre Archiv (je nach Branche) |
| Application Logs | 90 Tage |
| Debug/Trace Logs | 7 Tage |
| Netzwerk-Flow-Logs | 30 Tage |
Compliance-Anforderungen (DSGVO, BSI, NIS2) verlangen keine konkrete Zahl, aber „nachvollziehbare Aufbewahrung“ – in der Praxis 12 Monate für Security Events als sicherer Wert.
Log-Rotation ohne Backup = potentieller Datenverlust. logrotate-Konfiguration mit Kompression und Remote-Sync:
/var/log/auth.log {
daily
rotate 365
compress
delaycompress
missingok
notifempty
postrotate
rsync -a /var/log/auth.log.*.gz backup-server:/logs/$(hostname)/
endscript
}
Tools für kontinuierliche Log-Qualitätssicherung
| Tool | Zweck |
|---|---|
| Vector | Normalisierung, Anreicherung, Field-Mapping |
| Logstash | Parsing, Transformation, ECS-Normalisierung |
| sigma-cli | Testet, ob SIGMA-Rules auf Logs matchen (Qualitätssignal) |
| Fluent Bit | Leichtgewichtiger Forwarder, Field-Rename-Support |
| Graylog | Integriertes Log-Management mit Qualitäts-Alerts |
Stolperfallen
- Normalisierung aufgeschoben: „Machen wir später“ – danach hat niemand mehr Zeit
- ECS nur für manche Quellen: Halbherzig umgesetzt bringt nichts. Konsistenz über alle Quellen ist der Wert
- Log-Löschung als Hygiene-Maßnahme: Logs löschen, um Probleme zu beheben, ist forensisches Suizid
- Debug in SIEM: Teure Ingestion für sinnlose Events. Log-Level-Policy erzwingen
- Timestamps zu spät normalisieren: Normalisierung beim Eingang (am Collector) ist billiger als beim Query-Zeitpunkt
- Kein Monitoring der Log-Pipeline selbst: Pipeline-Ausfälle werden erst beim Incident bemerkt. Log-Volume-Alerting pflicht
Praxis-Checkliste
- Alle Log-Quellen auf UTC-Timestamps konfiguriert
- ISO 8601 mit Millisekunden als Standard in allen Quellen
- Feldnamen-Normalisierung auf ECS oder einheitliches Schema aktiv
- Syslog-Größenlimit auf min. 64k erhöht (RFC 5424 Mode)
- Logs werden in Echtzeit auf Remote-System geforwarded (kein Local-only)
- Retention-Policy pro Log-Typ dokumentiert und technisch umgesetzt
- Log-Level-Policy definiert: kein Debug im SIEM
- Log-Pipeline-Monitoring aktiv (Volume-Alert bei Drop > 20 %)
- Jährlicher Log-Qualitäts-Audit (Feldnamen, Timestamps, Truncation)
- Normalisierungsregeln versioniert (Git) und getestet
Fazit
Logging-Hygiene ist kein glamouröses Thema, aber es ist das Fundament, auf dem alles andere steht: Detection, Forensik, Compliance. Schlechte Logs sind aktiv schädlich – sie vermitteln ein falsches Sicherheitsgefühl und versagen im Moment, wo sie am meisten gebraucht werden. Die gute Nachricht: die häufigsten Probleme (Timestamps, Feldnamen, Forwarding) sind mit überschaubarem Aufwand lösbar. Ein halber Tag Log-Hygiene-Audit zahlt sich beim nächsten Incident hundertfach aus.
Wenn du tiefer einsteigen willst: Im Newsletter zeige ich jeden Monat konkrete Log-Normalisierungs-Rezepte, Vector-Konfigurationen und Log-Qualitäts-Checklisten für KMU. Trag dich ein.