Vertrauen auf Cookies ohne Validierung und Integritätsprüfung bei Sicherheitsentscheidungen

Beschreibung

Vertrauen auf Cookies ohne Validierung und Integritätsprüfung bei Sicherheitsentscheidungen ist eine Web-Sicherheitsschwachstelle, bei der Software Cookies für Authentifizierung, Autorisierung oder andere Sicherheitsentscheidungen verwendet, ohne die Herkunft oder Integrität des Cookies ordnungsgemäß zu validieren. Cookies werden clientseitig gespeichert und können leicht von Benutzern durch Browser-Entwicklertools, Browser-Erweiterungen oder durch direkte Manipulation von HTTP-Anfragen geändert werden. Wenn Anwendungen Cookie-Werten ohne Verifizierung vertrauen, können Angreifer Cookies fälschen oder manipulieren, um Authentifizierung zu umgehen, Privilegien zu eskalieren oder andere Benutzer zu imitieren.

Risiko

Cookie-Manipulation ist trivial für Angreifer - Cookies können direkt in Browsern oder durch Proxy-Tools bearbeitet werden. Wenn Sicherheitsentscheidungen auf unvalidierten Cookies beruhen, können Angreifer beliebige Werte setzen, um Authentifizierung zu umgehen (setzen von "authenticated=true"), Privilegien zu eskalieren (setzen von "role=admin") oder Identitäten anderer Benutzer anzunehmen. Diese Schwachstelle führt oft zu vollständiger Authentifizierungsumgehung, da viele fehlerhafte Implementierungen nur das Vorhandensein oder den Wert eines Cookies prüfen, ohne zu verifizieren, dass es legitim vom Server gesetzt wurde.

Lösung

Verlassen Sie sich niemals allein auf Cookie-Werte für Sicherheitsentscheidungen. Implementieren Sie serverseitige Session-Verwaltung, bei der Session-Identifikatoren auf serverseitig gespeicherte Session-Daten verweisen. Wenn Cookies sicherheitsrelevante Daten tragen müssen, implementieren Sie kryptografischen Integritätsschutz mit HMACs oder digitalen Signaturen. Verwenden Sie HttpOnly- und Secure-Flags auf sensitiven Cookies. Implementieren Sie ordnungsgemäße Session-Verwaltung mit serverseitiger Validierung. Für zustandslose Designs erwägen Sie signierte Tokens (wie JWTs) mit ordnungsgemäßer Signaturverifizierung.

Häufige Auswirkungen

AuswirkungDetails
ZugriffskontrolleBereich: Zugriffskontrolle

Schutzmechanismus umgehen - Angreifer manipulieren Cookies, um Authentifizierungs- oder Autorisierungsprüfungen zu umgehen.
ZugriffskontrolleBereich: Zugriffskontrolle

Privilegien erlangen oder Identität annehmen - Cookie-Manipulation ermöglicht Privilegieneskalation oder Benutzer-Impersonation.
IntegritätBereich: Integrität

Anwendungsdaten ändern - Gefälschte Cookies können Anwendungsverhalten und Datenintegrität beeinträchtigen.

Beispielcode

Verwundbarer Code

// Verwundbar: Cookie direkt für Autorisierung verwenden
import javax.servlet.http.*;

public class VulnerableServlet extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response) {
        String userRole = "guest";

        // Verwundbar: Rolle direkt aus Cookie ohne Validierung lesen
        Cookie[] cookies = request.getCookies();
        if (cookies != null) {
            for (Cookie c : cookies) {
                if (c.getName().equals("role")) {
                    userRole = c.getValue();  // Angreifer setzt: role=admin
                }
            }
        }

        // Verwundbar: Sicherheitsentscheidung basierend auf unvalidiertem Cookie
        if (userRole.equals("admin")) {
            showAdminPanel(response);  // Angreifer erhält Admin-Zugriff!
        } else {
            showUserPanel(response);
        }
    }
}
// Verwundbar: Authentifizierungsumgehung über Cookie
<?php
$authenticated = $_COOKIE['authenticated'] ?? '0';

// Verwundbar: Cookie für Authentifizierungsstatus vertrauen
if ($authenticated != '1') {
    // Benutzer nicht authentifiziert, versuche zu authentifizieren
    if (authenticateUser($_POST['username'], $_POST['password']) === true) {
        setcookie("authenticated", "1", time() + 3600);
        setcookie("username", $_POST['username'], time() + 3600);
    } else {
        die("Authentifizierung fehlgeschlagen");
    }
} else {
    // Verwundbar: Cookie sagt authentifiziert, also vertrauen
    // Angreifer setzt einfach authenticated=1 Cookie!
    $username = $_COOKIE['username'];
    echo "Willkommen zurück, $username";
}
?>
# Verwundbar: Flask-App verwendet Cookies für Zugriffskontrolle
from flask import Flask, request, make_response

app = Flask(__name__)

@app.route('/dashboard')
def vulnerable_dashboard():
    # Verwundbar: Benutzer-ID aus Cookie lesen
    user_id = request.cookies.get('user_id')
    is_admin = request.cookies.get('is_admin')

    if not user_id:
        return redirect('/login')

    # Verwundbar: Cookie-Werte direkt verwenden
    user_data = get_user_data(user_id)  # Angreifer setzt user_id auf beliebigen Benutzer

    # Verwundbar: Admin-Prüfung basierend auf Cookie
    if is_admin == 'true':  # Angreifer setzt is_admin=true
        return render_admin_dashboard(user_data)

    return render_user_dashboard(user_data)

Gefixter Code

// Gefixt: Serverseitige Session-Verwaltung
import javax.servlet.http.*;

public class FixedServlet extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response) {
        // Gefixt: HttpSession (serververwaltet) verwenden
        HttpSession session = request.getSession(false);

        if (session == null) {
            response.sendRedirect("/login");
            return;
        }

        // Gefixt: Rolle aus serverseitiger Session holen, nicht Cookie
        String userRole = (String) session.getAttribute("role");
        if (userRole == null) {
            userRole = "guest";
        }

        if ("admin".equals(userRole)) {
            showAdminPanel(response);
        } else {
            showUserPanel(response);
        }
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) {
        String username = request.getParameter("username");
        String password = request.getParameter("password");

        if (authenticateUser(username, password)) {
            HttpSession session = request.getSession(true);
            User user = getUserByUsername(username);

            // Gefixt: Rolle in serverseitiger Session speichern
            session.setAttribute("userId", user.getId());
            session.setAttribute("role", user.getRole());

            response.sendRedirect("/dashboard");
        }
    }
}
// Gefixt: Serverseitige Sessions mit HMAC-geschützten Cookies
<?php
session_start();  // PHP-Sessions anstelle roher Cookies verwenden

define('SECRET_KEY', getenv('SESSION_SECRET'));

function createSecureCookie($name, $value) {
    $timestamp = time();
    $data = json_encode(['value' => $value, 'timestamp' => $timestamp]);
    $signature = hash_hmac('sha256', $data, SECRET_KEY);
    $cookie_value = base64_encode($data) . '.' . $signature;
    setcookie($name, $cookie_value, [
        'expires' => time() + 3600,
        'httponly' => true,
        'secure' => true,
        'samesite' => 'Strict'
    ]);
}

function readSecureCookie($name) {
    if (!isset($_COOKIE[$name])) return null;

    $parts = explode('.', $_COOKIE[$name]);
    if (count($parts) !== 2) return null;

    list($data_b64, $signature) = $parts;
    $data = base64_decode($data_b64);

    // Gefixt: Signatur verifizieren
    $expected_sig = hash_hmac('sha256', $data, SECRET_KEY);
    if (!hash_equals($expected_sig, $signature)) {
        return null;  // Manipuliert!
    }

    $parsed = json_decode($data, true);

    // Gefixt: Zeitstempel prüfen um Replay zu verhindern
    if (time() - $parsed['timestamp'] > 3600) {
        return null;  // Abgelaufen
    }

    return $parsed['value'];
}

// Gefixt: Serverseitige Session verwenden
if (!isset($_SESSION['authenticated']) || $_SESSION['authenticated'] !== true) {
    if (authenticateUser($_POST['username'], $_POST['password'])) {
        $_SESSION['authenticated'] = true;
        $_SESSION['user_id'] = getUserId($_POST['username']);
        $_SESSION['role'] = getUserRole($_POST['username']);
    } else {
        die("Authentifizierung fehlgeschlagen");
    }
}

// Gefixt: Aus Server-Session lesen, nicht Cookie
$user_id = $_SESSION['user_id'];
$role = $_SESSION['role'];
?>
# Gefixt: Flask mit serverseitigen Sessions und signierten Cookies
from flask import Flask, request, session, redirect
from flask_session import Session
import secrets

app = Flask(__name__)
app.secret_key = secrets.token_hex(32)  # Stärker geheimer Schlüssel

# Serverseitige Sessions verwenden
app.config['SESSION_TYPE'] = 'redis'
Session(app)

@app.route('/dashboard')
def fixed_dashboard():
    # Gefixt: Serverseitige Session prüfen
    if 'user_id' not in session:
        return redirect('/login')

    # Gefixt: Benutzerdaten aus Datenbank mit Session-user_id holen
    user = get_user_by_id(session['user_id'])
    if not user:
        session.clear()
        return redirect('/login')

    # Gefixt: Rolle aus Datenbank prüfen, nicht Session/Cookie
    if user.is_admin:
        return render_admin_dashboard(user)

    return render_user_dashboard(user)

@app.route('/login', methods=['POST'])
def fixed_login():
    username = request.form['username']
    password = request.form['password']

    if authenticate(username, password):
        user = get_user(username)
        # Gefixt: Nur user_id in Session speichern
        session['user_id'] = user.id
        session['login_time'] = time.time()
        # is_admin nicht speichern - jedes Mal aus DB prüfen
        return redirect('/dashboard')

    return "Login fehlgeschlagen", 401

CVE-Beispiele

  • CVE-2009-1549: Authentifizierungsumgehung durch Setzen von Cookies auf spezifische hartcodierte Werte.
  • CVE-2009-1619: Admin-Privilegien erlangt durch Setzen von "admin"-Cookie auf Wert "1".
  • CVE-2009-0864: CMS-Admin-Panel-Zugriff durch Setzen von "login"-Cookie auf "OK".
  • CVE-2008-5784: Dating-Anwendung Admin-Zugriff über admin-Cookie gesetzt auf "1".

Referenzen

  1. MITRE Corporation. "CWE-784: Reliance on Cookies without Validation and Integrity Checking in a Security Decision." https://cwe.mitre.org/data/definitions/784.html
  2. OWASP. "Session Management Cheat Sheet." https://cheatsheetseries.owasp.org/cheatsheets/Session_Management_Cheat_Sheet.html
  3. OWASP. "Testing for Cookies Attributes." OWASP Testing Guide.