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
| Auswirkung | Details |
|---|---|
| Zugriffskontrolle | Bereich: 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
-
MITRE Corporation. "CWE-270: Privilege Context Switching Error." Common Weakness Enumeration. https://cwe.mitre.org/data/definitions/270.html
-
OWASP Foundation. "Broken Access Control." OWASP Top 10. https://owasp.org/Top10/A01_2021-Broken_Access_Control/
-
Microsoft. "Security Zones in Internet Explorer." https://docs.microsoft.com/en-us/troubleshoot/browsers/security-zones