Logging übermäßiger Daten
Beschreibung
Logging übermäßiger Daten ist eine Sicherheitsschwachstelle, bei der Software eine übermäßige Menge an Informationen loggt, was Log-Dateien schwer verarbeitbar macht und möglicherweise wichtige Sicherheitsereignisse verdeckt. Obwohl Logging essentiell für Sicherheitsüberwachung und forensische Analyse ist, kann übermäßiges Logging kontraproduktiv sein. Zu viele Log-Daten erzeugen Rauschen, das die Fähigkeit von Administratoren behindert, anomale Bedingungen zu erkennen, bieten Deckung für Angreifer, indem deren Aktivitäten in irrelevanten Einträgen begraben werden, erschweren Debugging und verbrauchen erhebliche Systemressourcen einschließlich Festplattenplatz und CPU-Zeit.
Risiko
Übermäßiges Logging erzeugt mehrere Sicherheits- und Betriebsrisiken. Angreifer können bösartige Aktivitäten in massiven Log-Volumen verstecken, wissend dass Administratoren unwahrscheinlich jeden Eintrag überprüfen. Größe Log-Dateien verbrauchen schnell Festplattenplatz und können potenziell Denial of Service verursachen, wenn Speicher erschöpft ist. Die Verarbeitung übermäßiger Logs verbraucht CPU-Ressourcen und verschlechtert die Systemleistung. Während Sicherheitsvorfällen wird forensische Analyse extrem schwierig, wenn relevante Ereignisse im Rauschen begraben sind.
Lösung
Implementieren Sie geeignete Logging-Levels für jede Umgebung - ausführliches Debug-Logging in der Entwicklung, minimales essentielles Logging in der Produktion. Unterdrücken Sie doppelte Log-Meldungen durch Zusammenfassung wiederholter Einträge (z.B. "letzte Meldung X mal wiederholt"). Konfigurieren Sie maximale Log-Datei-Größen mit Rotation und Archivierung. Implementieren Sie Log-Sampling für High-Volume-Events. Verwenden Sie strukturiertes Logging, um effizientes Filtern zu ermöglichen. Definieren Sie klare Richtlinien, was auf jeder Schweregradestufe geloggt werden sollte und was nicht.
Häufige Auswirkungen
| Auswirkung | Details |
|---|---|
| Verfügbarkeit | Bereich: Verfügbarkeit DoS: Ressourcenverbrauch - Übermäßiges Logging verbraucht Festplattenplatz und CPU-Ressourcen und verschlechtert die Systemleistung. |
| Verantwortlichkeit | Bereich: Verantwortlichkeit, Nicht-Abstreitbarkeit Aktivitäten verbergen - Größe Log-Volumen bieten Deckung für Angreifer und verbergen bösartige Aktivitäten im Rauschen. |
| Integrität | Bereich: Integrität Reduzierter forensischer Wert - Übergroße Logs werden für Sicherheitsanalyse und Incident Response unpraktisch. |
Beispielcode
Verwundbarer Code
// Verwundbar: Jede Anfrage im Detail loggen
public class VulnerableRequestHandler {
private static final Logger logger = Logger.getLogger(VulnerableRequestHandler.class);
public void handleRequest(HttpServletRequest request) {
// Verwundbar: Loggt vollständige Anfrage-Details für jede Anfrage
logger.info("Anfrage empfangen von: " + request.getRemoteAddr());
logger.info("Anfrage-Methode: " + request.getMethod());
logger.info("Anfrage-URI: " + request.getRequestURI());
logger.info("Query-String: " + request.getQueryString());
// Loggt alle Header
Enumeration<String> headers = request.getHeaderNames();
while (headers.hasMoreElements()) {
String header = headers.nextElement();
logger.info("Header " + header + ": " + request.getHeader(header));
}
// In hochfrequentierten Umgebungen erzeugt dies Gigabytes an Logs
processRequest(request);
}
}
# Verwundbar: Logging in engen Schleifen
import logging
logger = logging.getLogger(__name__)
def vulnerable_process_data(large_dataset):
# Verwundbar: Loggt jedes Element in großem Datensatz
for i, item in enumerate(large_dataset):
logger.debug(f"Verarbeite Element {i}: {item}") # Millionen von Log-Einträgen
logger.debug(f"Element-Details: {item.get_all_attributes()}")
logger.debug(f"Element-Metadaten: {item.metadata}")
result = process_item(item)
logger.debug(f"Element {i} verarbeitet, Ergebnis: {result}")
logger.debug(f"Speichernutzung nach Element {i}: {get_memory_usage()}")
# Für 1 Million Elemente erstellt dies 5+ Millionen Log-Einträge
Gefixter Code
// Gefixt: Angemessenes Logging mit Levels und Zusammenfassung
public class FixedRequestHandler {
private static final Logger logger = Logger.getLogger(FixedRequestHandler.class);
private static final AtomicInteger requestCount = new AtomicInteger(0);
private static final int LOG_SAMPLE_RATE = 100;
public void handleRequest(HttpServletRequest request) {
int count = requestCount.incrementAndGet();
// Gefixt: Nur periodisch Zusammenfassung loggen
if (count % LOG_SAMPLE_RATE == 0) {
logger.info("Verarbeitet " + count + " Anfragen");
}
// Gefixt: Debug-Level für detaillierte Info (in Produktion deaktiviert)
if (logger.isDebugEnabled()) {
logger.debug("Anfrage: " + request.getMethod() + " " + request.getRequestURI());
}
try {
processRequest(request);
} catch (Exception e) {
// Gefixt: Nur tatsächliche Fehler mit relevantem Kontext loggen
logger.error("Anfrage fehlgeschlagen: " + request.getMethod() + " " + request.getRequestURI()
+ " - " + e.getMessage());
}
}
}
# Gefixt: Kontrolliertes Logging mit Sampling und Zusammenfassung
import logging
from collections import Counter
logger = logging.getLogger(__name__)
def fixed_process_data(large_dataset):
total_items = len(large_dataset)
processed_count = 0
error_count = 0
error_summary = Counter()
# Gefixt: Start und Ende loggen, nicht jedes Element
logger.info(f"Starte Verarbeitung von {total_items} Elementen")
for i, item in enumerate(large_dataset):
try:
result = process_item(item)
processed_count += 1
# Gefixt: Fortschritts-Logging in Intervallen
if (i + 1) % 10000 == 0:
logger.info(f"Fortschritt: {i + 1}/{total_items} Elemente verarbeitet")
except ProcessingError as e:
error_count += 1
error_summary[type(e).__name__] += 1
# Gefixt: Nur erste Fehler jedes Typs loggen
if error_summary[type(e).__name__] <= 3:
logger.warning(f"Verarbeitungsfehler: {e}")
# Gefixt: Zusammenfassung am Ende
logger.info(f"Abgeschlossen: {processed_count}/{total_items} erfolgreich, {error_count} Fehler")
if error_summary:
logger.warning(f"Fehler-Zusammenfassung: {dict(error_summary)}")
// Gefixt: Minimales Produktions-Logging
const express = require('express');
const app = express();
// Gefixt: Konfigurierbare Logging-Levels
const LOG_LEVEL = process.env.LOG_LEVEL || 'info';
app.use((req, res, next) => {
const start = Date.now();
res.on('finish', () => {
const duration = Date.now() - start;
// Gefixt: Einzelne Zeile pro Anfrage, nur essentielle Info
const logData = {
method: req.method,
path: req.path,
status: res.statusCode,
duration: duration + 'ms'
};
// Gefixt: Error-Level für Probleme, Info für normales
if (res.statusCode >= 500) {
console.error('Anfragefehler:', JSON.stringify(logData));
} else if (LOG_LEVEL === 'debug') {
console.log('Anfrage:', JSON.stringify(logData));
}
});
next();
});
CVE-Beispiele
- CVE-2007-0421: Server loggte übermäßige Daten beim Empfang fehlerhafter Header und verbrauchte Festplattenplatz.
- CVE-2002-1154: Anwendung beschränkte Update-Zugriff nicht und erlaubte Angreifern, Fehler-Logs mit übermäßigen Einträgen zu füllen.
Referenzen
- MITRE Corporation. "CWE-779: Logging of Excessive Data." https://cwe.mitre.org/data/definitions/779.html
- OWASP. "Logging Cheat Sheet." https://cheatsheetseries.owasp.org/cheatsheets/Logging_Cheat_Sheet.html
- NIST. "Guide to Computer Security Log Management." SP 800-92.