Unvollständige interne Zustandsunterscheidung
Beschreibung
Unvollständige interne Zustandsunterscheidung ist eine Schwachstelle, die auftritt, wenn ein Produkt seinen aktuellen Betriebszustand nicht korrekt bestimmt und fälschlicherweise annimmt, es befinde sich in Zustand X, während es tatsächlich in Zustand Y operiert. Diese Fehlwahrnehmung führt dazu, dass das System sicherheitsrelevante Operationen falsch ausführt, da das Verhalten davon abhängt, in welchem Zustand das System zu sein glaubt im Vergleich zu seinem tatsächlichen Zustand. Die Schwäche resultiert oft aus nicht behandelten Fehlerbedingungen, fehlerhaftem Verfolgen von Zustandsübergängen oder der Unfähigkeit, Operationsschritte außerhalb der Reihenfolge zu verwalten. Wenn Sicherheitsentscheidungen auf falschen Zustandsannahmen basieren, können Zugriffskontrollen, Authentifizierung und andere Schutzmaßnahmen umgangen werden.
Risiko
Unvollständige Zustandsunterscheidung kann zu Sicherheitsumgehungen und unautorisiertem Zugriff führen. Authentifizierungssysteme, die den Zustand verlieren, können nicht authentifizierte Benutzer als authentifiziert behandeln. Transaktionssysteme, die Zustände verwechseln, können Operationen in der falschen Reihenfolge verarbeiten und unautorisierte Änderungen ermöglichen. Zugriffskontrollsysteme können Berechtigungen gewähren, die für einen Zustand angemessen sind, während sie sich tatsächlich in einem anderen befinden. Die Schwachstelle ist besonders gefährlich, da sie schwer zu erkennen sein kann -- das System scheint normal zu funktionieren, während es mit falschen Sicherheitsannahmen operiert. Race Conditions und Fehlerbehandlungsfehler lösen diese Zustandsverwirrungsprobleme häufig aus.
Lösung
Implementieren Sie explizite Zustandsmaschinen mit klaren Zustandsübergängen. Validieren Sie Zustandsvoraussetzungen, bevor zustandsabhängige Operationen ausgeführt werden. Verwenden Sie Aufzählungstypen oder Konstanten für Zustände anstelle impliziter boolescher Kombinationen. Implementieren Sie umfassende Fehlerbehandlung, die ordnungsgemäß in Fehlerzustande übergeht. Protokollieren Sie Zustandsübergänge für Debugging und Audit. Verwenden Sie Assertions zur Verifizierung erwarteter Zustände während der Entwicklung. Erwägen Sie formale Verifikation für kritische Zustandsmaschinen. Stellen Sie sicher, dass alle Fehlerpfade den Zustand ordnungsgemäß aktualisieren.
Häufige Auswirkungen
| Auswirkung | Details |
|---|---|
| Integrität | Bereich: Integrität Operationen werden mit falschen Annahmen über den Systemzustand ausgeführt, was zu fehlerhaftem Verhalten führt. |
| Andere | Bereich: Ändere Unerwarteter Zustand führt zu unvorhersagbarem Verhalten, das Sicherheitskontrollen kompromittieren kann. |
Beispielcode und Lösung
Verwundbarer Code
// Verwundbar: Zustand mit booleschen Flags verfolgt, leicht zu verwechseln
typedef struct {
int authenticated;
int admin;
int transaction_started;
} SessionState;
void vulnerable_process_command(SessionState *state, char *cmd) {
if (strcmp(cmd, "logout") == 0) {
state->authenticated = 0;
// Verwundbar: Admin-Flag vergessen zu löschen
// Zustand ist jetzt verwirrt - nicht authentifiziert, aber immer noch Admin
}
if (state->admin) {
// Verwundbar: Kann Admin-Befehle ausführen, wenn nicht authentifiziert
execute_admin_command(cmd);
}
}
# Verwundbar: Zustandsverwirrung bei der Transaktionsbehandlung
class VulnerableTransaction:
def __init__(self):
self.started = False
self.committed = False
self.rolled_back = False
def start(self):
self.started = True
def commit(self):
# Verwundbar: Prüft nicht, ob bereits zurückgerollt
self.committed = True
def rollback(self):
# Verwundbar: Prüft nicht, ob bereits committed
self.rolled_back = True
def execute(self, operation):
# Verwundbar: Kann in ungültigen Zuständen ausführen
# (committed UND rolled_back könnten beide True sein)
if self.started:
perform_operation(operation)
// Verwundbar: Zustandsverwirrung bei der Authentifizierung
public class VulnerableAuth {
private boolean loginAttempted = false;
private boolean passwordVerified = false;
private boolean mfaVerified = false;
public void attemptLogin(String password) {
loginAttempted = true;
if (checkPassword(password)) {
passwordVerified = true;
}
// Verwundbar: loginAttempted bleibt auch bei Fehlschlag true
}
public void verifyMfa(String code) {
if (checkMfaCode(code)) {
mfaVerified = true;
}
// Verwundbar: MFA kann ohne Passwortverifizierung geprüft werden
}
public boolean isAuthenticated() {
// Verwundbar: Zustandsflags können inkonsistent sein
return loginAttempted && (passwordVerified || mfaVerified);
// Sollte BEIDES Passwort UND MFA erfordern
}
}
Sichere Lösung
// Behoben: Explizite Zustandsmaschine mit einzelner Zustandsvariable
typedef enum {
STATE_UNAUTHENTICATED,
STATE_AUTHENTICATED_USER,
STATE_AUTHENTICATED_ADMIN,
STATE_TRANSACTION_ACTIVE,
STATE_ERROR
} SessionStateType;
typedef struct {
SessionStateType state;
} Session;
int secure_process_command(Session *session, char *cmd) {
if (strcmp(cmd, "logout") == 0) {
// Behoben: Einzelner Zustandsübergang, keine Verwirrung
session->state = STATE_UNAUTHENTICATED;
return 0;
}
// Behoben: Explizite Zustandsprüfung
if (session->state != STATE_AUTHENTICATED_ADMIN) {
return -1; // Nicht autorisiert
}
return execute_admin_command(cmd);
}
# Behoben: Zustandsmaschine mit expliziten Übergängen
from enum import Enum, auto
class TransactionState(Enum):
NOT_STARTED = auto()
ACTIVE = auto()
COMMITTED = auto()
ROLLED_BACK = auto()
ERROR = auto()
class SecureTransaction:
def __init__(self):
self.state = TransactionState.NOT_STARTED
def start(self):
if self.state != TransactionState.NOT_STARTED:
raise InvalidStateError(f"Cannot start from state {self.state}")
self.state = TransactionState.ACTIVE
def commit(self):
if self.state != TransactionState.ACTIVE:
raise InvalidStateError(f"Cannot commit from state {self.state}")
self.state = TransactionState.COMMITTED
def rollback(self):
if self.state != TransactionState.ACTIVE:
raise InvalidStateError(f"Cannot rollback from state {self.state}")
self.state = TransactionState.ROLLED_BACK
def execute(self, operation):
# Behoben: Nur im ACTIVE-Zustand ausführen
if self.state != TransactionState.ACTIVE:
raise InvalidStateError(f"Cannot execute in state {self.state}")
perform_operation(operation)
// Behoben: Explizite Authentifizierungs-Zustandsmaschine
public class SecureAuth {
public enum AuthState {
UNAUTHENTICATED,
PASSWORD_VERIFIED,
FULLY_AUTHENTICATED
}
private AuthState state = AuthState.UNAUTHENTICATED;
public void attemptLogin(String password) {
if (state != AuthState.UNAUTHENTICATED) {
throw new IllegalStateException("Already in authentication flow");
}
if (checkPassword(password)) {
state = AuthState.PASSWORD_VERIFIED;
}
// Zustand bleibt UNAUTHENTICATED bei Fehlschlag
}
public void verifyMfa(String code) {
// Behoben: Passwortverifizierung zuerst erfordern
if (state != AuthState.PASSWORD_VERIFIED) {
throw new IllegalStateException("Must verify password first");
}
if (checkMfaCode(code)) {
state = AuthState.FULLY_AUTHENTICATED;
} else {
// Behoben: Fehlgeschlagene MFA setzt auf nicht authentifiziert zurück
state = AuthState.UNAUTHENTICATED;
}
}
public boolean isAuthenticated() {
// Behoben: Einzelne klare Zustandsprüfung
return state == AuthState.FULLY_AUTHENTICATED;
}
public void logout() {
state = AuthState.UNAUTHENTICATED;
}
}
CVE-Beispiele
Für diese CWE sind keine spezifischen CVEs aufgeführt. Das Schwachstellenmuster tritt auf in:
- Authentifizierungssystemen mit komplexem Zustand
- Transaktionsverarbeitungssystemen
- Protokollimplementierungen
Referenzen
- MITRE Corporation. "CWE-372: Incomplete Internal State Distinction." https://cwe.mitre.org/data/definitions/372.html