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

AuswirkungDetails
IntegritätBereich: Integrität

Operationen werden mit falschen Annahmen über den Systemzustand ausgeführt, was zu fehlerhaftem Verhalten führt.
AndereBereich: Ä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

  1. MITRE Corporation. "CWE-372: Incomplete Internal State Distinction." https://cwe.mitre.org/data/definitions/372.html