Authentifizierungsumgehung durch als unveränderlich angenommene Daten
Beschreibung
Authentifizierungsumgehung durch als unveränderlich angenommene Daten ist eine Schwachstelle, die auftritt, wenn ein Authentifizierungsschema Schlüsseldatenelemente verwendet, von denen Entwickler fälschlicherweise annehmen, dass sie nicht von Angreifern kontrolliert oder geändert werden können. Gängige Beispiele umfassen das Vertrauen auf clientseitige Cookies, versteckte Formularfelder, Umgebungsvariablen oder HTTP-Header für Authentifizierungsentscheidungen. Obwohl diese Mechanismen aus Sicht eines legitimen Benutzers schwer zu ändern erscheinen mögen, können Angreifer sie leicht mit Browser-Entwicklertools, Proxy-Interceptors oder benutzerdefinierten HTTP-Clients manipulieren. Daten, die vom Client stammen oder durch den Client geleitet werden, können nicht ohne serverseitige Validierung für Sicherheitsentscheidungen vertraut werden.
Risiko
Das Vertrauen auf als unveränderlich angenommene Daten für die Authentifizierung erzeugt trivial ausnutzbare Schwachstellen. Angreifer können leicht verfügbare Tools wie Browser-Entwicklerkonsolen, HTTP-Proxy-Interceptors oder einfache Befehlszeilen-Dienstprogramme verwenden, um Cookies, versteckte Felder und Header zu modifizieren. Das Risiko ist schwerwiegend, da die Ausnutzung minimale technische Fähigkeiten erfordert, aber eine vollständige Authentifizierungsumgehung gewährt. Reale Exploits haben gezeigt, dass Angreifer administrativen Zugang einfach durch Setzen eines Cookie-Werts auf "true" oder Ändern eines versteckten Formularfelds erlangen. Diese Schwachstellen bleiben oft unerkannt, da sie während normaler Tests korrekt funktionieren -- nur gezielte Manipulation offenbart den Fehler. Die Auswirkungen reichen von unautorisiertem Datenzugriff bis zur vollständigen Systemkompromittierung, abhängig von der Zugriffsebene, die durch den verwundbaren Mechanismus kontrolliert wird.
Lösung
Vertrauen Sie niemals clientseitig bereitgestellten Daten für Authentifizierungsentscheidungen ohne serverseitige Verifizierung. Speichern Sie den Authentifizierungsstatus ausschließlich serverseitig unter Verwendung kryptographisch sicherer Session-Identifikatoren. Wenn clientseitige Tokens verwendet werden müssen, signieren Sie sie kryptographisch (z.B. mit HMAC oder JWT mit Signaturen) und verifizieren Sie Signaturen serverseitig, bevor Sie Angaben vertrauen. Implementieren Sie ordnungsgemäßes Session-Management mit serverseitigen Session-Speichern. Validieren und bereinigen Sie alle Eingaben von Clients und behandeln Sie versteckte Formularfelder, Cookies und Header mit demselben Misstrauen wie sichtbare Benutzereingaben. Verwenden Sie vom Framework bereitgestellte Authentifizierungsmechanismen anstelle eigener Lösungen. Wenden Sie Defense-in-Depth an -- selbst wenn eine Schicht umgangen wird, sollten zusätzliche Prüfungen unautorisierten Zugang verhindern.
Häufige Auswirkungen
| Auswirkung | Details |
|---|---|
| Zugriffskontrolle | Bereich: Zugriffskontrolle Angreifer können die Authentifizierung vollständig umgehen, indem sie als unveränderlich angenommene Daten modifizieren, und erhalten unautorisierten Zugang als beliebiger Benutzer einschließlich Administratoren. |
| Integrität, Vertraulichkeit | Bereich: Integrität, Vertraulichkeit Bei umgangener Authentifizierung können Angreifer auf sensible Daten zugreifen, Datensätze ändern und jede Aktion ausführen, die der imitierte Benutzer ausführen könnte. |
Beispielcode und Lösung
Verwundbarer Code (Java)
Die folgenden Beispiele zeigen Authentifizierungsumgehung durch als unveränderlich angenommene Daten:
// Verwundbar: Vertrauen auf Cookie-Wert für Authentifizierung
import javax.servlet.http.*;
public class VulnerableAuthServlet extends HttpServlet {
protected void doGet(HttpServletRequest request,
HttpServletResponse response) {
// Verwundbar: Authentifizierungsstatus aus Cookie lesen
Cookie[] cookies = request.getCookies();
boolean authenticated = false;
String role = "user";
if (cookies != null) {
for (Cookie cookie : cookies) {
// Verwundbar: Vertrauen auf clientkontrollierten Cookie
if ("authenticated".equals(cookie.getName())) {
authenticated = Boolean.parseBoolean(cookie.getValue());
}
if ("role".equals(cookie.getName())) {
role = cookie.getValue(); // Angreifer setzt auf "admin"
}
}
}
// Angreifer setzt einfach den Cookie authenticated=true
if (authenticated) {
if ("admin".equals(role)) {
// Voller Admin-Zugang nur durch Cookie-Änderung!
showAdminPanel(response);
} else {
showUserDashboard(response);
}
} else {
redirectToLogin(response);
}
}
}
# Verwundbar: Vertrauen auf verstecktes Formularfeld für Autorisierung
from flask import Flask, request, render_template
app = Flask(__name__)
@app.route('/transfer', methods=['POST'])
def transfer_funds():
# Verwundbar: Benutzer-ID aus verstecktem Formularfeld
user_id = request.form.get('user_id') # Verstecktes Feld im Formular
amount = float(request.form.get('amount'))
target_account = request.form.get('target_account')
# Angreifer ändert versteckte user_id, um einen anderen Benutzer zu imitieren
# Keine serverseitige Verifizierung des tatsächlich angemeldeten Benutzers
perform_transfer(user_id, target_account, amount)
return "Transfer completed"
@app.route('/admin', methods=['GET'])
def admin_panel():
# Verwundbar: Vertrauen auf Query-Parameter für Admin-Prüfung
is_admin = request.args.get('admin', 'false')
# Angreifer besucht einfach /admin?admin=true
if is_admin.lower() == 'true':
return render_template('admin_panel.html')
else:
return "Access Denied", 403
<?php
// Verwundbar: Vertrauen auf mehrere als unveränderlich angenommene Quellen
// Verwundbar: Cookie-basierte Authentifizierung
$authenticated = isset($_COOKIE['logged_in']) && $_COOKIE['logged_in'] === 'true';
$username = $_COOKIE['username'] ?? '';
// Verwundbar: Verstecktes Formularfeld für Autorisierung
$user_level = $_POST['user_level'] ?? 'guest';
// Verwundbar: HTTP-Header für Admin-Umgehung
$is_admin = isset($_SERVER['HTTP_X_ADMIN']) && $_SERVER['HTTP_X_ADMIN'] === 'true';
if (!$authenticated) {
header('Location: /login.php');
exit;
}
// Angreifer setzt X-Admin: true Header und erhält Admin-Zugang
if ($is_admin || $user_level === 'admin') {
include 'admin_dashboard.php';
} else {
include 'user_dashboard.php';
}
?>
Sichere Lösung (Java)
// Behoben: Serverseitiges Session-Management für Authentifizierung
import javax.servlet.http.*;
import java.security.SecureRandom;
import java.util.*;
public class SecureAuthServlet extends HttpServlet {
// Serverseitiger Session-Speicher
private static final Map<String, UserSession> sessions =
new ConcurrentHashMap<>();
protected void doGet(HttpServletRequest request,
HttpServletResponse response) {
// Behoben: Session-ID aus Cookie holen, serverseitig validieren
String sessionId = null;
Cookie[] cookies = request.getCookies();
if (cookies != null) {
for (Cookie cookie : cookies) {
if ("session_id".equals(cookie.getName())) {
sessionId = cookie.getValue();
break;
}
}
}
// Behoben: Session-Daten serverseitig nachschlagen
UserSession session = (sessionId != null) ? sessions.get(sessionId) : null;
// Behoben: Prüfen, ob Session existiert und nicht abgelaufen ist
if (session == null || session.isExpired()) {
redirectToLogin(response);
return;
}
// Behoben: Rolle aus serverseitiger Session holen, nicht vom Client
if ("admin".equals(session.getRole())) {
showAdminPanel(response);
} else {
showUserDashboard(response);
}
}
protected void doPost(HttpServletRequest request,
HttpServletResponse response) {
String username = request.getParameter("username");
String password = request.getParameter("password");
// Gegen Datenbank authentifizieren
User user = authenticateUser(username, password);
if (user != null) {
// Behoben: Serverseitige Session erstellen
String sessionId = generateSecureSessionId();
UserSession session = new UserSession(user.getId(), user.getRole());
sessions.put(sessionId, session);
// Nur Session-ID an Client senden (nicht den Auth.-Status)
Cookie sessionCookie = new Cookie("session_id", sessionId);
sessionCookie.setHttpOnly(true);
sessionCookie.setSecure(true);
sessionCookie.setMaxAge(3600);
response.addCookie(sessionCookie);
response.sendRedirect("/dashboard");
} else {
response.sendRedirect("/login?error=invalid");
}
}
private String generateSecureSessionId() {
byte[] bytes = new byte[32];
new SecureRandom().nextBytes(bytes);
return Base64.getUrlEncoder().encodeToString(bytes);
}
}
# Behoben: Serverseitiges Session-Management
from flask import Flask, request, session, redirect, url_for
from functools import wraps
import secrets
app = Flask(__name__)
app.secret_key = secrets.token_bytes(32)
# Serverseitiger Session-Speicher (in Produktion Redis oder Datenbank verwenden)
user_sessions = {}
def login_required(f):
@wraps(f)
def decorated(*args, **kwargs):
# Behoben: Session serverseitig verifizieren
session_id = session.get('session_id')
if not session_id or session_id not in user_sessions:
return redirect(url_for('login'))
# Behoben: Benutzerinfo aus serverseitigem Speicher holen
user_data = user_sessions[session_id]
if user_data.get('expired'):
return redirect(url_for('login'))
return f(user_data, *args, **kwargs)
return decorated
def admin_required(f):
@wraps(f)
def decorated(*args, **kwargs):
session_id = session.get('session_id')
if not session_id or session_id not in user_sessions:
return redirect(url_for('login'))
user_data = user_sessions[session_id]
# Behoben: Rolle serverseitig geprüft, nicht vom Client
if user_data.get('role') != 'admin':
return "Access Denied", 403
return f(user_data, *args, **kwargs)
return decorated
@app.route('/transfer', methods=['POST'])
@login_required
def transfer_funds(user_data):
# Behoben: user_id aus serverseitiger Session holen, nicht aus Formular
user_id = user_data['user_id'] # Aus authentifizierter Session
amount = float(request.form.get('amount'))
target_account = request.form.get('target_account')
# Jetzt mit verifizierter user_id vom Server
perform_transfer(user_id, target_account, amount)
return "Transfer completed"
@app.route('/admin')
@admin_required
def admin_panel(user_data):
# Behoben: Rolle vor Erreichen dieses Punktes serverseitig verifiziert
return render_template('admin_panel.html')
@app.route('/login', methods=['POST'])
def login():
username = request.form.get('username')
password = request.form.get('password')
user = authenticate_user(username, password)
if user:
# Behoben: Serverseitige Session erstellen
session_id = secrets.token_urlsafe(32)
user_sessions[session_id] = {
'user_id': user.id,
'role': user.role, # Rolle aus Datenbank
'created_at': time.time()
}
session['session_id'] = session_id
return redirect(url_for('dashboard'))
return redirect(url_for('login', error='invalid'))
Die Behebung speichert den Authentifizierungsstatus serverseitig und sendet nur einen kryptographisch zufälligen Session-Identifikator an den Client.
Ausgenutzt in der Praxis
Cookie-basierte Admin-Umgehung (Webanwendungen, 2002)
CVE-2002-1730 und CVE-2002-1734 dokumentierten Webanwendungen, die administrativen Zugang gewährten, wenn Benutzer Authentifizierungs-Cookies auf "true" setzten, was eine triviale Umgehung der Authentifizierung ermöglichte.
Manipulation versteckter Felder (E-Commerce, fortlaufend)
Mehrere E-Commerce-Plattformen wurden durch Änderung versteckter Formularfelder mit Preisen, Mengen oder Benutzer-IDs ausgenutzt, wodurch Angreifer Transaktionen manipulieren könnten.
Tools zum Testen und Ausnutzen
-
Burp Suite -- Web-Sicherheitstool zum Abfangen und Ändern von HTTP-Anfragen einschließlich Cookies und versteckter Felder.
-
OWASP ZAP -- Open-Source Web-Anwendungs-Sicherheitsscanner mit Anfrage-Abfangfunktionen.
-
Browser DevTools -- Integrierte Browser-Tools zum Ändern von Cookies, Formularen und Headern.
CVE-Beispiele
-
CVE-2002-1730 -- Authentifizierungsumgehung durch Setzen eines Cookies auf "true".
-
CVE-2002-1734 -- Authentifizierungsumgehung durch Cookie-Manipulation.
-
CVE-2002-2064 -- Admin-Zugang durch Setzen eines Cookie-Werts.
-
CVE-2005-1708 -- Umgehung durch Setzen einer Admin-Variable auf true.
-
CVE-2005-1787 -- Rechteeskalation durch Manipulation versteckter Felder.
Referenzen
-
MITRE Corporation. "CWE-302: Authentication Bypass by Assumed-Immutable Data." Common Weakness Enumeration. https://cwe.mitre.org/data/definitions/302.html
-
OWASP Foundation. "Broken Access Control." OWASP Top Ten. https://owasp.org/Top10/A01_2021-Broken_Access_Control/
-
OWASP Foundation. "Session Management Cheat Sheet." https://cheatsheetseries.owasp.org/cheatsheets/Session_Management_Cheat_Sheet.html