Fehler beim Wechsel des Privilegienkontexts

Beschreibung

Fehler beim Wechsel des Privilegienkontexts ist eine Schwachstelle, die auftritt, wenn ein Produkt Privilegien beim Wechsel zwischen verschiedenen Kontexten mit unterschiedlichen Privilegien oder Kontrollbereichen nicht ordnungsgemäß verwaltet. Diese Schwäche entsteht, wenn Anwendungen zwischen Sicherheitsdomänen, Vertrauenszonen oder Benutzerkontexten wechseln, ohne die aktive Privilegienstufe korrekt an den Zielkontext anzupassen. Das Ergebnis kann sein, dass Operationen, die mit einem Satz von Berechtigungen ausgeführt werden sollten, tatsächlich mit den Privilegien eines anderen Kontexts ausgeführt werden, was unbefugten Zugriff auf Ressourcen oder Funktionalität ermöglicht.

Risiko

Unsachgemäßer Privilegienkontextwechsel erzeugt erhebliche Sicherheitsrisiken, indem er Privilegienlecks über Sicherheitsgrenzen hinweg ermöglicht. Wenn Anwendungen Kontextwechsel nicht ordnungsgemäß verwalten, können Benutzer Privilegien aus vorherigen Kontexten erben und möglicherweise Zugang zu Ressourcen erhalten, die sie nicht erreichen sollten. In Webbrowsern manifestiert sich dies als Cross-Domain-Schwachstellen, bei denen Skripte von nicht vertrauenswürdigen Seiten auf Daten aus vertrauenswürdigen Zonen zugreifen können. In Betriebssystemen kann dies Prozessen ermöglichen, erhöhte Privilegien beim Übergang zu eingeschränkten Kontexten beizubehalten. Angreifer, die Kontextwechselfehler identifizieren, können diese für Privilegieneskalation, Cross-Site-Scripting über Zonen hinweg oder unbefugten Zugriff auf geschützte Ressourcen ausnutzen.

Lösung

Verwalten Sie Privilegieneinstellungen während aller Kontextübergänge sorgfältig und stellen Sie explizites Vertrauenszonen-Management sicher. Implementieren Sie klare Privilegiengrenzen zwischen verschiedenen Sicherheitskontexten und verifizieren Sie, dass Privilegienstufen beim Überschreiten von Grenzen ordnungsgemäß angepasst werden. Führen Sie Code mit den minimal erforderlichen Privilegien aus und erstellen Sie isolierte Konten für spezifische Aufgaben, um die Auswirkungen von Kontextwechselfehlern zu begrenzen. Wenden Sie das Prinzip der Privilegientrennung an und erfordern Sie mehrere Bedingungen, bevor Sie Zugang zu sensiblen Ressourcen gewähren. Entwerfen Sie Systeme mit expliziten Kontextwechselfunktionen, die atomar den gesamten privilegienbezogenen Zustand aktualisieren. Testen Sie Kontextübergänge gründlich, insbesondere für Grenzfälle wie Navigationsverlauf (Zurück-Taste) und Callback-Ausführung über Vertrauensgrenzen hinweg.

Häufige Auswirkungen

AuswirkungDetails
ZugriffskontrolleBereich: Zugriffskontrolle

Benutzer können die Identität oder Privilegienstufe eines anderen Benutzers in einem separaten Kontext mit unterschiedlichen Berechtigungen annehmen. Dies ermöglicht unbefugten Zugriff auf geschützte Ressourcen und potenzielle Offenlegung von Anmeldedaten oder sensiblen Daten anderer Benutzer. Kontextwechselfehler können auch ermöglichen, dass Code aus nicht vertrauenswürdigen Quellen mit erhöhten Privilegien ausgeführt wird.

Beispielcode

Anfälliger Code (JavaScript/Web-Kontext)

Die folgenden Beispiele demonstrieren Privilegienkontextwechsel-Schwachstellen:

// Anfällig: Webanwendung mit Kontextwechselfehlern
class VulnerableContextManager {

    constructor() {
        this.currentContext = 'untrusted';
        this.trustedDomains = ['secure.example.com', 'admin.example.com'];
    }

    handleNavigation(newUrl, navigationType) {
        const previousContext = this.currentContext;

        // Anfällig: Zurück-Taste-Navigation wechselt Kontext nicht ordnungsgemäß
        if (navigationType === 'back') {
            // Kontext bleibt von der Seite, VON der navigiert wird
            // nicht der Seite, ZU der navigiert wird
            // Benutzer geht von vertrauenswürdig -> nicht vertrauenswürdig, behält aber vertrauenswürdigen Kontext
            this.loadPage(newUrl);
            // currentContext nicht aktualisiert!
        } else {
            this.updateContext(newUrl);
            this.loadPage(newUrl);
        }
    }

    executeCallback(callback, sourceContext) {
        // Anfällig: Callback wird im aktuellen Kontext ausgeführt, nicht im Quellkontext
        // Callback, der im nicht vertrauenswürdigen Kontext registriert wurde, wird ausgeführt, nachdem
        // Benutzer zum vertrauenswürdigen Kontext navigiert
        callback();  // Läuft mit vertrauenswürdigen Privilegien!
    }
}
// Anfällig: C-Prozess-Kontextwechsel ohne Privilegienverwaltung
#include <unistd.h>
#include <sys/types.h>

void vulnerable_context_switch(uid_t target_uid) {
    // Aktueller Prozess läuft als root

    // Anfällig: Wechsel des Benutzerkontexts ohne Verwaltung aller Privilegien
    setuid(target_uid);  // Kann auf manchen Systemen stillschweigend fehlschlagen

    // Prozess fährt fort - war der Wechsel erfolgreich?
    // Andere Privilegienaspekte (Gruppen, Capabilities) werden möglicherweise nicht aktualisiert

    // Wenn dies forkt, um externen Code auszuführen, kann es immer noch Probleme geben
    execve("/user/provided/path", args, env);
}

void vulnerable_zone_transition(void) {
    // Prozess startete in privilegierter Zone

    // Anfällig: Übergang zu eingeschränkter Zone ohne Löschen des Zustands
    chroot("/restricted/environment");
    chdir("/");

    // Läuft immer noch als root!
    // Dateihandles aus privilegierter Zone noch offen
    // Capabilities nicht abgelegt

    // Angreifer kann aus chroot ausbrechen und auf privilegierte Ressourcen zugreifen
}
// Anfällig: Java-Anwendung mit Sicherheitskontext-Problemen
public class VulnerableSecurityContext {

    private SecurityContext currentContext;

    public void processRequest(Request request, Callback callback) {
        SecurityContext requestContext = determineContext(request);
        SecurityContext originalContext = currentContext;

        // Zu Request-Kontext wechseln
        currentContext = requestContext;

        try {
            // Im Request-Kontext verarbeiten
            processInContext(request);

            // Anfällig: Callback wurde möglicherweise in anderem Kontext registriert
            // aber wird mit aktuellem erhöhten Kontext ausgeführt
            if (callback != null) {
                callback.execute();  // Läuft mit requestContext-Privilegien
            }
        } finally {
            // Anfällig: Wenn Exception vor finally auftritt, wird Kontext nicht wiederhergestellt
            currentContext = originalContext;
        }
    }

    public void loadThirdPartyCode(String url, SecurityZone zone) {
        // Anfällig: Drittanbieter-Code lädt in falscher Zone
        if (zone == SecurityZone.TRUSTED) {
            // Benutzer beabsichtigte nicht vertrauenswürdige Zone, aber Code läuft als vertrauenswürdig
            // aufgrund von URL-Parsing-Schwachstelle
            executeInTrustedContext(loadCode(url));
        }
    }
}

Korrigierter Code (JavaScript/Web-Kontext)

// Korrigiert: Ordnungsgemäße Sicherheitskontext-Verwaltung
public class SecureSecurityContext {

    private final ThreadLocal<SecurityContext> currentContext =
        new ThreadLocal<>();
    private final Map<Callback, SecurityContext> callbackContexts =
        new ConcurrentHashMap<>();

    public void processRequest(Request request, Callback callback) {
        SecurityContext requestContext = determineContext(request);
        SecurityContext originalContext = currentContext.get();

        // Validieren, dass Kontextübergang erlaubt ist
        if (!isTransitionAllowed(originalContext, requestContext)) {
            throw new SecurityException("Ungültiger Kontextübergang");
        }

        currentContext.set(requestContext);

        try {
            processInContext(request);

            // Korrigiert: Callback in seinem registrierten Kontext ausführen
            if (callback != null) {
                executeCallbackInOriginalContext(callback);
            }
        } finally {
            // Immer ursprünglichen Kontext wiederherstellen
            currentContext.set(originalContext);
        }
    }

    public void registerCallback(Callback callback) {
        // Kontext zum Registrierungszeitpunkt erfassen
        callbackContexts.put(callback, currentContext.get());
    }

    private void executeCallbackInOriginalContext(Callback callback) {
        SecurityContext callbackContext = callbackContexts.get(callback);
        SecurityContext executionContext = currentContext.get();

        if (callbackContext == null) {
            throw new SecurityException("Callback hat keinen registrierten Kontext");
        }

        // Zu ursprünglichem Kontext des Callbacks wechseln
        currentContext.set(callbackContext);
        try {
            callback.execute();
        } finally {
            currentContext.set(executionContext);
        }
    }
}
// Korrigiert: Ordnungsgemäßer C-Privilegien-Kontextwechsel
#include <unistd.h>
#include <sys/types.h>
#include <grp.h>
#include <sys/prctl.h>

int secure_context_switch(uid_t target_uid, gid_t target_gid) {
    // Zuerst alle zusätzlichen Gruppen löschen
    if (setgroups(0, NULL) != 0) {
        return -1;
    }

    // Zuerst Gruppenprivileg ablegen (muss geschehen während noch root)
    if (setgid(target_gid) != 0) {
        return -1;
    }

    // Gruppenänderung verifizieren
    if (getgid() != target_gid || getegid() != target_gid) {
        return -1;
    }

    // Benutzerprivileg ablegen
    if (setuid(target_uid) != 0) {
        return -1;
    }

    // Benutzeränderung verifizieren - KRITISCH
    if (getuid() != target_uid || geteuid() != target_uid) {
        return -1;
    }

    // Sicherstellen, dass wir Privilegien nicht wiedererlangen können
    if (setuid(0) != -1) {
        // Wenn dies erfolgreich ist, ist Privilegienablegung fehlgeschlagen!
        _exit(1);
    }

    return 0;
}

int secure_zone_transition(const char* restricted_path) {
    // Alle unnötigen Dateideskriptoren vor Übergang schließen
    close_all_fds_except(STDERR_FILENO);

    // Zu eingeschränktem Root wechseln
    if (chroot(restricted_path) != 0) {
        return -1;
    }

    if (chdir("/") != 0) {
        return -1;
    }

    // JETZT Privilegien ablegen
    if (secure_context_switch(UNPRIVILEGED_UID, UNPRIVILEGED_GID) != 0) {
        return -1;
    }

    // Verifizieren, dass wir in eingeschränkter Umgebung sind
    // (zusätzliche Prüfungen basierend auf Sicherheitsanforderungen)

    return 0;
}

Die Korrektur stellt ordnungsgemäße Kontexterfassung für Callbacks sicher, validiert Kontextübergänge, verifiziert, dass Privilegienablegung erfolgreich war, und erhält Kontextisolation über Sicherheitsgrenzen hinweg.


Ausgenutzt in der Praxis

Browser Cross-Domain-Schwachstellen (Mehrere Browser, Historisch)

Webbrowser haben zahlreiche Privilegienkontextwechsel-Schwachstellen erfahren, bei denen Navigationsaktionen wie die "Zurück"-Taste dazu führten, dass Skripte mit Privilegien aus der falschen Sicherheitszone ausgeführt wurden. Diese Schwachstellen ermöglichten es bösartigen Websites, auf Daten aus vertrauenswürdigen Zonen oder lokale Dateien zuzugreifen.

Zonenübergangs-Exploits in Windows (Windows-Systeme, Historisch)

Windows Internet-Sicherheitszonen wurden durch Kontextwechselfehler ausgenutzt, bei denen Inhalte, die aus nicht vertrauenswürdigen Zonen geladen wurden, mit Local-Machine-Zone-Privilegien ausgeführt werden könnten. Angreifer nutzten diese Schwachstellen, um aus Browser-Sandboxen auszubrechen und beliebigen Code auszuführen.

Container-Escape durch Kontextwechsel (Container-Umgebungen, Fortlaufend)

Container- und Sandbox-Technologien waren anfällig für Kontextwechselfehler, bei denen Prozesse Capabilities oder Dateihandles aus privilegierten Kontexten behalten können, nachdem sie in eingeschränkte Container übergegangen sind, was Container-Escape ermöglicht.


Tools zum Testen/Ausnutzen

  • BurpSuite — Web-Sicherheitstest-Tool zur Identifizierung von Kontextwechsel-Schwachstellen in Webanwendungen.

  • Browser Security Handbook — Referenz zum Verständnis von Browser-Sicherheitszonen-Implementierungen und Tests.

  • Container Security Scanner — Tools zur Identifizierung von Privilegienkontext-Problemen in containerisierten Umgebungen.


CVE-Beispiele

  • CVE-2002-1688 — Webbrowser Cross-Domain-Schwachstelle ausgelöst durch "Zurück"-Taste-Navigation.

  • CVE-2003-1026 — Ähnliche Browser Cross-Domain-Schwachstelle in Navigationshandhabung.

  • CVE-2002-1770 — Drittanbieter-Code in unsicherer Browser-Zone aufgrund von Kontextfehler ausgeführt.

  • CVE-2005-2263 — Callback-Ausführung in geändertem Sicherheitskontext nach Zonenübergang.


Referenzen

  1. MITRE Corporation. "CWE-270: Privilege Context Switching Error." Common Weakness Enumeration. https://cwe.mitre.org/data/definitions/270.html

  2. OWASP Foundation. "Broken Access Control." OWASP Top 10. https://owasp.org/Top10/A01_2021-Broken_Access_Control/

  3. Microsoft. "Security Zones in Internet Explorer." https://docs.microsoft.com/en-us/troubleshoot/browsers/security-zones