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

AuswirkungDetails
ZugriffskontrolleBereich: Zugriffskontrolle

Umgehung des Schutzmechanismus - Angreifer können Eingaben modifizieren, um Sicherheitsprüfungen vollständig zu umgehen.
ZugriffskontrolleBereich: Zugriffskontrolle

Privilegien erlangen oder Identität annehmen - Manipulierte Eingaben können unbefugten Zugriff gewähren oder die Nachahmung anderer Benutzer ermöglichen.
VariiertBereich: 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

  1. MITRE Corporation. "CWE-807: Reliance on Untrusted Inputs in a Security Decision." https://cwe.mitre.org/data/definitions/807.html
  2. OWASP. "Insecure Direct Object References." https://owasp.org/www-project-web-security-testing-guide/
  3. OWASP. "Session Management Cheat Sheet." https://cheatsheetseries.owasp.org/cheatsheets/Session_Management_Cheat_Sheet.html