Beobachtbare Antwortdiskrepanz
Beschreibung
Beobachtbare Antwortdiskrepanz ist eine Schwachstelle, die auftritt, wenn ein Produkt unterschiedliche Antworten auf eingehende Anfragen basierend auf dem internen Zustand liefert und dadurch Informationen an unbefugte Akteure preisgibt. Im Gegensatz zu timing-basierten Diskrepanzen betrifft diese Schwäche speziell Variationen im Inhalt, der Struktur oder dem Typ der vom System zurückgegebenen Antworten. Häufige Manifestationen umfassen unterschiedliche Fehlermeldungen für gültige versus ungültige Benutzernamen, unterschiedliche HTTP-Statuscodes basierend auf dem Authentifizierungsstatus oder variierende Antwortinhalte, die offenlegen, ob bestimmte Ressourcen existieren. Angreifer analysieren diese Antwortunterschiede, um gültige Konten zu enumerieren, versteckte Funktionalität zu entdecken, Systeme zu fingerprinting oder Informationen für weitere Angriffe zu sammeln.
Risiko
Beobachtbare Antwortdiskrepanzen erzeugen erhebliche Sicherheitsrisiken, indem sie Angreifern ermöglichen, sensible Informationen durch sorgfältige Analyse von Systemantworten zu sammeln. Benutzernamen-Enumeration ermöglicht Angreifern, Listen gültiger Konten für gezielte Passwortangriffe, Credential Stuffing oder Social-Engineering-Kampagnen zu erstellen. System-Fingerprinting durch Antwortanalyse hilft Angreifern, Softwareversionen, Konfigurationen und potenzielle Schwachstellen zur Ausnutzung zu identifizieren. In Authentifizierungssystemen können Antwortunterschiede Passwortrichtlinien, Kontosperrstatus oder Multi-Faktor-Authentifizierungsstatus offenlegen. Diese Informationslecks transformieren blinde Angriffe in gezielte und erhöhen erheblich die Wahrscheinlichkeit einer erfolgreichen Kompromittierung bei gleichzeitiger Reduzierung der Zeit und Ressourcen, die Angreifer investieren müssen.
Lösung
Implementieren Sie konsistente, generische Fehlermeldungen für alle Authentifizierungs- und Autorisierungsfehlerszenarien. Verwenden Sie identische Antwortnachrichten wie "Authentifizierung fehlgeschlagen" oder "Ungültige Anmeldedaten", unabhängig davon, ob der Benutzername, das Passwort oder beides falsch ist. Stellen Sie sicher, dass HTTP-Statuscodes für verschiedene Fehlertypen konsistent bleiben – vermeiden Sie die Rückgabe von 401 für gültige Benutzer und 404 für ungültige. Implementieren Sie Antwortnormalisierung an der Anwendungsgrenze, um interne Statusindikatoren zu entfernen, bevor Daten an Clients zurückgegeben werden. Konfigurieren Sie Webserver und Frameworks, um einheitliche Fehlerseiten zurückzugeben. Für sensible Operationen erwägen Sie die Implementierung fester Antwortzeiten zusammen mit konsistenten Meldungen. Prüfen Sie Anwendungsantworten regelmäßig mit automatisierten Tools, um unbeabsichtigte Informationslecks in Fehlerbehandlungspfaden zu erkennen.
Häufige Auswirkungen
| Auswirkung | Details |
|---|---|
| Vertraulichkeit, Zugriffskontrolle | Bereich: Vertraulichkeit, Zugriffskontrolle Angreifer können Antwortunterschiede analysieren, um sensible Anwendungsdaten zu lesen und Schutzmechanismen zu umgehen. Benutzernamen-Enumeration ermöglicht gezielte Angriffe, während System-Fingerprinting Konfigurationsdetails enthüllt, die bei der Identifizierung ausnutzbarer Schwachstellen helfen. |
| Vertraulichkeit | Bereich: Vertraulichkeit Antwortdiskrepanzen können die Existenz geschützter Ressourcen, gültiger Anmeldedaten, interner Systemzustände und Konfigurationsdetails offenlegen. Dieses Informationsleck kompromittiert die Datenvertraulichkeit, selbst wenn der direkte Zugriff auf die Daten geschützt bleibt. |
Beispielcode
Anfälliger Code (Java)
Der folgende Code demonstriert einen anfälligen Login-Endpunkt, bei dem unterschiedliche Fehlermeldungen enthüllen, ob ein Benutzername existiert:
@RestController
public class VulnerableAuthController {
@Autowired
private UserRepository userRepository;
@Autowired
private PasswordEncoder passwordEncoder;
@PostMapping("/api/login")
public ResponseEntity<?> login(@RequestBody LoginRequest request) {
// Anfällig: Unterschiedliche Antworten enthüllen Benutzernamen-Gültigkeit
User user = userRepository.findByUsername(request.getUsername());
if (user == null) {
// Antwort A: Enthüllt, dass Benutzername nicht existiert
return ResponseEntity.status(HttpStatus.NOT_FOUND)
.body(new ErrorResponse("Benutzer nicht gefunden"));
}
if (!passwordEncoder.matches(request.getPassword(), user.getPasswordHash())) {
// Antwort B: Enthüllt, dass Benutzername existiert aber Passwort falsch
return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
.body(new ErrorResponse("Falsches Passwort"));
}
// Prüfen ob Konto gesperrt ist
if (user.isLocked()) {
// Antwort C: Enthüllt, dass Konto existiert und gesperrt ist
return ResponseEntity.status(HttpStatus.FORBIDDEN)
.body(new ErrorResponse("Konto ist gesperrt"));
}
String token = generateToken(user);
return ResponseEntity.ok(new AuthResponse(token));
}
}
Die Schwachstelle besteht, weil jeder Fehlerfall einen unterschiedlichen HTTP-Statuscode und Fehlermeldung zurückgibt, was Angreifern ermöglicht festzustellen: (1) ob ein Benutzername existiert, (2) ob das Passwort falsch ist und (3) ob das Konto gesperrt ist.
Korrigierter Code (Java)
@RestController
public class SecureAuthController {
@Autowired
private UserRepository userRepository;
@Autowired
private PasswordEncoder passwordEncoder;
// Generische Fehlermeldung für alle Authentifizierungsfehler
private static final String AUTH_FAILURE_MESSAGE = "Ungültiger Benutzername oder Passwort";
private static final HttpStatus AUTH_FAILURE_STATUS = HttpStatus.UNAUTHORIZED;
@PostMapping("/api/login")
public ResponseEntity<?> login(@RequestBody LoginRequest request) {
// Immer dieselben Operationen durchführen unabhängig von Benutzerexistenz
User user = userRepository.findByUsername(request.getUsername());
// Dummy-Benutzer für Timing-Konsistenz erstellen wenn Benutzer nicht existiert
String passwordToCheck = (user != null) ? user.getPasswordHash() : getDummyHash();
// Immer Passwortprüfung durchführen für konsistentes Timing
boolean passwordValid = passwordEncoder.matches(
request.getPassword(),
passwordToCheck
);
// Alle Bedingungen prüfen aber identischen Fehler zurückgeben
if (user == null || !passwordValid || user.isLocked()) {
// Spezifischen Grund intern für Sicherheitsüberwachung loggen
logAuthFailure(request.getUsername(), user, passwordValid);
// Generische Antwort zurückgeben - gleiche Nachricht, gleicher Status für alle Fehler
return ResponseEntity.status(AUTH_FAILURE_STATUS)
.body(new ErrorResponse(AUTH_FAILURE_MESSAGE));
}
String token = generateToken(user);
return ResponseEntity.ok(new AuthResponse(token));
}
private String getDummyHash() {
// Vorberechneter Hash für konsistentes Timing
return "$2a$10$dummyhashfordummyuserxxxxxxxxxxxxxxxxxxxxxxxx";
}
private void logAuthFailure(String username, User user, boolean passwordValid) {
// Internes Logging für Sicherheitsteam - niemals an Client offengelegt
if (user == null) {
securityLogger.warn("Anmeldeversuch für nicht existierenden Benutzer: {}", username);
} else if (!passwordValid) {
securityLogger.warn("Ungültiges Passwort für Benutzer: {}", username);
} else if (user.isLocked()) {
securityLogger.warn("Anmeldeversuch auf gesperrtes Konto: {}", username);
}
}
}
Die Korrektur gibt identische HTTP-Statuscodes und Fehlermeldungen für alle Authentifizierungsfehler zurück und behält detailliertes internes Logging für Sicherheitsüberwachung bei. Ein Dummy-Passwort-Hash stellt konsistente Verarbeitungszeit auch für nicht existierende Benutzer sicher.
Ausgenutzt in der Praxis
Yahoo E-Mail-Enumeration (Yahoo, 2013-2014)
Angreifer nutzten Yahoos Passwort-Zurücksetzen-Funktionalität aus, die unterschiedliche Antworten für gültige und ungültige E-Mail-Adressen zurückgab. Durch Automatisierung von Anfragen an den Passwort-Zurücksetzen-Endpunkt und Analyse der variierenden Antworten erstellten Angreifer massive Listen gültiger Yahoo-E-Mail-Adressen. Diese Listen wurden anschließend in Credential-Stuffing-Angriffen und Phishing-Kampagnen verwendet und trugen zum Breach bei, der über 3 Milliarden Yahoo-Konten betraf.
LinkedIn Benutzer-Enumeration für Data Scraping (LinkedIn, 2021)
Angreifer nutzten LinkedIns API-Endpunkte aus, die Antwortdiskrepanzen aufwiesen, die enthüllten, ob Benutzer-IDs gültig waren. Durch systematisches Abfragen der API und Analyse verschiedener Antwortmuster scrapeten Angreifer Profildaten von über 700 Millionen LinkedIn-Benutzern. Die kompilierten Daten wurden anschließend in Darknet-Foren verkauft und legten persönliche und berufliche Informationen der LinkedIn-Benutzerbasis offen.
Keycloak Client-Enumeration (Mehrere Organisationen, 2024)
Eine Schwachstelle in Keycloak, der beliebten Open-Source-Identitäts- und Zugriffsverwaltungslösung, ermöglichte Angreifern, registrierte Clients auf Realms durch beobachtbare Antwortdiskrepanzen zu enumerieren. Der Server gab "Invalid Request" für existierende Clients zurück, aber "Client not found" für nicht existierende. Diese Informationsoffenlegung betraf Organisationen, die Keycloak für Authentifizierung über ihre Anwendungen hinweg nutzen.
Tools zum Testen/Ausnutzen
-
Burp Suite Intruder — Automatisiertes Tool zum Senden parametrisierter Anfragen und Analysieren von Antwortunterschieden zur Erkennung von Enumerationsschwachstellen.
-
OWASP ZAP — Open-Source-Webanwendungs-Sicherheitsscanner, der Antwortdiskrepanzen durch aktives Scannen und Fuzzing-Techniken erkennen kann.
-
Wfuzz — Webanwendungs-Fuzzer, der Antwortdiskrepanzen durch Vergleich von HTTP-Antworten über verschiedene Eingaben hinweg identifizieren kann.
CVE-Beispiele
-
CVE-2025-24023 — Flask-AppBuilder Benutzer-Enumerationsschwachstelle, bei der Zeitunterschiede bei Datenbankauthentifizierung gültige Benutzernamen enthüllen.
-
CVE-2024-45052 — Fides Webserver timing-basierte Benutzernamen-Enumeration ermöglicht nicht authentifizierten Angreifern, gültige Benutzernamen zu ermitteln.
-
CVE-2001-1483 — Anwendung gibt inkonsistente Antworten zurück, die Angreifern ermöglichen, gültige Benutzernamen zu enumerieren.
-
CVE-2004-0243 — Betriebssystem enthüllt Passwort-Korrektheit durch unterschiedliche Fehlermeldungen vor vollständiger Authentifizierung.
-
CVE-2004-1428 — FTP-Server fragt nur nach Passwort, wenn Benutzername existiert, und ermöglicht Benutzer-Enumeration.
Referenzen
-
MITRE Corporation. "CWE-204: Observable Response Discrepancy." Common Weakness Enumeration. https://cwe.mitre.org/data/definitions/204.html
-
OWASP Foundation. "Testing for Account Enumeration and Guessable User Account." OWASP Web Security Testing Guide. https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/03-Identity_Management_Testing/04-Testing_for_Account_Enumeration_and_Guessable_User_Account
-
Pentest-Tools.com. "6 Techniques for Account Enumeration in a Penetration Test." https://pentest-tools.com/blog/account-enumeration-techniques-pentesting
-
PortSwigger. "Username Enumeration via Response Timing." Web Security Academy. https://portswigger.net/web-security/authentication/password-based/lab-username-enumeration-via-response-timing