Vertrauen auf nicht vertrauenswürdige Eingaben bei einer Sicherheitsentscheidung
Beschreibung
Vertrauen auf nicht vertrauenswürdige Eingaben bei einer Sicherheitsentscheidung tritt auf, wenn Software Eingaben verwendet, die von nicht vertrauenswürdigen Akteuren modifiziert werden können, um sicherheitskritische Entscheidungen über Authentifizierung, Autorisierung oder Zugriffskontrolle zu treffen. Entwickler nehmen oft fälschlicherweise an, dass bestimmte Eingaben nicht geändert werden können - Cookies, Umgebungsvariablen, versteckte Formularfelder, HTTP-Header oder URL-Parameter - aber Angreifer, die angepasste Clients, abfangende Proxys oder direkte API-Aufrufe verwenden, können alle vom Client bereitgestellten Daten modifizieren. Wenn Sicherheitsentscheidungen von diesen nicht validierten Werten abhängen, können Angreifer Zugriffskontrollen umgehen, Privilegien eskalieren oder andere Benutzer nachahmen.
Risiko
Diese Schwachstelle ermöglicht die direkte Umgehung von Sicherheitskontrollen. Angreifer können Cookies modifizieren, um verschiedene Benutzeridentitäten anzunehmen, versteckte Felder ändern, um Preise oder Berechtigungen zu ändern, HTTP-Header manipulieren, um IP-basierte Beschränkungen zu umgehen, oder Umgebungsvariablen fälschen, um erhöhte Privilegien zu erlangen. Die Auswirkungen reichen von unbefugtem Zugriff auf sensible Daten über Privilegieneskalation bis hin zur vollständigen Systemkompromittierung. Die Schwachstelle ist besonders heimtückisch, weil die Anwendung Sicherheitsprüfungen zu implementieren scheint - sie verlassen sich nur auf Eingaben, die der Angreifer kontrolliert. Vertrauen in vom Client bereitgestellte Daten ist ein fundamentales Sicherheits-Antimuster.
Lösung
Vertrauen Sie niemals client-bereitgestellten Eingaben für Sicherheitsentscheidungen. Speichern Sie autoritative Sicherheitszustande nur serverseitig unter Verwendung sicherer Sitzungsverwaltung. Wenn clientseitige Speicherung notwendig ist, verwenden Sie kryptografischen Integritätsschutz (HMAC, digitale Signaturen) und Verschlüsselung. Validieren Sie alle Eingaben gegen serverseitige autoritative Zustände. Implementieren Sie Defense-in-Depth durch Duplizierung clientseitiger Sicherheitsprüfungen auf dem Server. Verwenden Sie geprüft Frameworks, die Authentifizierungszustände automatisch verwalten. Identifizieren Sie alle Eingaben, die Sicherheitsentscheidungen beeinflussen könnten, und verfolgen Sie deren Ursprünge. Für DNS-basierte Entscheidungen implementieren Sie zusätzliche Verifizierungsmechanismen. In PHP deaktivieren Sie register_globals und vermeiden Sie das Extrahieren nicht vertrauenswürdiger Daten in die Symboltabelle.
Häufige Auswirkungen
| Auswirkung | Details |
|---|---|
| Zugriffskontrolle | Bereich: Zugriffskontrolle Umgehung des Schutzmechanismus - Angreifer können Eingaben modifizieren, um Sicherheitsprüfungen vollständig zu umgehen. |
| Zugriffskontrolle | Bereich: Zugriffskontrolle Privilegien erlangen oder Identität annehmen - Manipulierte Eingaben können unbefugten Zugriff gewähren oder die Nachahmung anderer Benutzer ermöglichen. |
| Variiert | Bereich: Variiert je nach Kontext Sonstiges - Konsequenzen hängen davon ab, was die Sicherheitsentscheidung schützt: Datenoffenlegung, Codeausführung, finanzielle Verluste usw. |
Beispielcode
Anfälliger Code
// Anfällig: Liest Benutzerrolle aus Cookie
public class VulnerableRoleCheck {
public void doPost(HttpServletRequest request, HttpServletResponse response) {
Cookie[] cookies = request.getCookies();
String role = "user"; // Standardrolle
for (Cookie cookie : cookies) {
if (cookie.getName().equals("role")) {
// Anfällig: Vertraut Cookie-Wert für Autorisierung
role = cookie.getValue();
}
}
if (role.equals("admin")) {
// Angreifer kann Cookie "role=admin" setzen, um Zugriff zu erlangen
showAdminPanel(response);
} else {
showUserPanel(response);
}
}
}
// Anfällig: Authentifizierung via Cookie
<?php
function vulnerable_auth_check() {
// Anfällig: Vertraut Cookie für Authentifizierung
$authenticated = false;
if (isset($_COOKIE['authenticated'])) {
// Angreifer setzt Cookie "authenticated=true"
$authenticated = ($_COOKIE['authenticated'] === 'true');
}
if ($authenticated) {
show_protected_content();
} else {
show_login_form();
}
}
?>
# Anfällig: Vertraut verstecktem Formularfeld
from flask import Flask, request
app = Flask(__name__)
@app.route('/purchase', methods=['POST'])
def vulnerable_purchase():
# Anfällig: Preis aus verstecktem Formularfeld
price = float(request.form.get('price', 0))
item_id = request.form.get('item_id')
# Angreifer modifiziert verstecktes Feld, um 0,01 EUR zu bezahlen
process_payment(price)
deliver_item(item_id)
return "Kauf abgeschlossen"
Korrigierter Code
// Korrigiert: Serverseitige Rollenverwaltung
public class FixedRoleCheck {
public void doPost(HttpServletRequest request, HttpServletResponse response) {
// Korrigiert: Rolle aus serverseitiger Sitzung holen
HttpSession session = request.getSession(false);
if (session == null) {
redirectToLogin(response);
return;
}
// Rolle serverseitig gespeichert, nicht im Cookie
String role = (String) session.getAttribute("role");
if ("admin".equals(role)) {
showAdminPanel(response);
} else {
showUserPanel(response);
}
}
}
// Korrigiert: Serverseitige Sitzungs-Authentifizierung
<?php
session_start();
function fixed_auth_check() {
// Korrigiert: Prüft serverseitige Sitzung, nicht Cookie
if (isset($_SESSION['authenticated']) &&
$_SESSION['authenticated'] === true &&
isset($_SESSION['user_id'])) {
// Überprüfen, ob Sitzung nicht abgelaufen ist
if (time() - $_SESSION['last_activity'] < SESSION_TIMEOUT) {
$_SESSION['last_activity'] = time();
show_protected_content();
return;
}
}
// Nicht authentifiziert oder Sitzung abgelaufen
session_destroy();
show_login_form();
}
?>
# Korrigiert: Serverseitige Preisabfrage
from flask import Flask, request, session
app = Flask(__name__)
@app.route('/purchase', methods=['POST'])
def fixed_purchase():
item_id = request.form.get('item_id')
# Korrigiert: Preis aus Server-Datenbank holen, nicht vom Client
item = get_item_from_database(item_id)
if not item:
return "Artikel nicht gefunden", 404
# Server-autoritativen Preis verwenden
price = item['price']
# Überprüfen, ob Benutzer Kaufberechtigung hat
if not session.get('user_id'):
return "Nicht authentifiziert", 401
process_payment(session['user_id'], price)
deliver_item(session['user_id'], item_id)
return "Kauf abgeschlossen"
Verwandte CWEs
- CWE-693: Versagen des Schutzmechanismus (Eltern)
- CWE-302: Authentifizierungsumgehung durch angenommene unveränderliche Daten (Kind)
- CWE-350: Vertrauen auf Reverse-DNS-Auflösung für sicherheitskritische Aktion (Kind)
- CWE-784: Vertrauen auf Cookies ohne Validierung und Integritätsprüfung (Kind)
- CWE-602: Clientseitige Durchsetzung serverseitiger Sicherheit (verwandt)
Referenzen
- MITRE Corporation. "CWE-807: Reliance on Untrusted Inputs in a Security Decision." https://cwe.mitre.org/data/definitions/807.html
- OWASP. "Insecure Direct Object References." https://owasp.org/www-project-web-security-testing-guide/
- OWASP. "Session Management Cheat Sheet." https://cheatsheetseries.owasp.org/cheatsheets/Session_Management_Cheat_Sheet.html