Incomplete Internal State Distinction

Description

Incomplete Internal State Distinction is a vulnerability that occurs when a product fails to accurately determine its current operational state, mistakenly assuming it is in state X when it actually operates in state Y. This misperception causes the system to perform security-relevant operations incorrectly because the behavior depends on which state the system believes it's in versus its actual state. The weakness often results from unhandled error conditions, failure to track state transitions properly, or inability to manage out-of-order operational steps. When security decisions are made based on incorrect state assumptions, access controls, authentication, and other protections can be bypassed.

Risk

Incomplete state distinction can lead to security bypasses and unauthorized access. Authentication systems that lose track of state may treat unauthenticated users as authenticated. Transaction systems that confuse states may process operations in the wrong order, allowing unauthorized modifications. Access control systems may grant permissions appropriate for one state while actually in another. The vulnerability is particularly dangerous because it can be difficult to detect - the system appears to function normally while operating with incorrect security assumptions. Race conditions and error handling failures often trigger these state confusion issues.

Solution

Implement explicit state machines with clear state transitions. Validate state preconditions before performing state-dependent operations. Use enumerated types or constants for states rather than implicit boolean combinations. Implement comprehensive error handling that properly transitions to error states. Log state transitions for debugging and audit. Use assertions to verify expected states during development. Consider formal verification for critical state machines. Ensure all error paths properly update state.

Common Consequences

ImpactDetails
IntegrityScope: Integrity

Operations execute with wrong assumptions about system state, causing incorrect behavior.
OtherScope: Other

Unexpected state leads to unpredictable behavior that may compromise security controls.

Example Code

Vulnerable Code

// Vulnerable: State tracked with boolean flags, easy to confuse
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;
        // Vulnerable: Forgot to clear admin flag
        // State is now confused - not authenticated but still admin
    }

    if (state->admin) {
        // Vulnerable: May execute admin commands when not authenticated
        execute_admin_command(cmd);
    }
}
# Vulnerable: State confusion in transaction handling
class VulnerableTransaction:
    def __init__(self):
        self.started = False
        self.committed = False
        self.rolled_back = False

    def start(self):
        self.started = True

    def commit(self):
        # Vulnerable: Doesn't check if already rolled back
        self.committed = True

    def rollback(self):
        # Vulnerable: Doesn't check if already committed
        self.rolled_back = True

    def execute(self, operation):
        # Vulnerable: Can execute in invalid states
        # (committed AND rolled_back could both be True)
        if self.started:
            perform_operation(operation)
// Vulnerable: Authentication state confusion
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;
        }
        // Vulnerable: loginAttempted stays true even on failure
    }

    public void verifyMfa(String code) {
        if (checkMfaCode(code)) {
            mfaVerified = true;
        }
        // Vulnerable: Can verify MFA without password verification
    }

    public boolean isAuthenticated() {
        // Vulnerable: State flags can be inconsistent
        return loginAttempted && (passwordVerified || mfaVerified);
        // Should require BOTH password AND MFA
    }
}

Fixed Code

// Fixed: Explicit state machine with single state variable
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) {
        // Fixed: Single state transition, no confusion
        session->state = STATE_UNAUTHENTICATED;
        return 0;
    }

    // Fixed: Explicit state check
    if (session->state != STATE_AUTHENTICATED_ADMIN) {
        return -1;  // Not authorized
    }

    return execute_admin_command(cmd);
}
# Fixed: State machine with explicit transitions
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):
        # Fixed: Only execute in ACTIVE state
        if self.state != TransactionState.ACTIVE:
            raise InvalidStateError(f"Cannot execute in state {self.state}")
        perform_operation(operation)
// Fixed: Explicit authentication state machine
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;
        }
        // State remains UNAUTHENTICATED on failure
    }

    public void verifyMfa(String code) {
        // Fixed: Require password verification first
        if (state != AuthState.PASSWORD_VERIFIED) {
            throw new IllegalStateException("Must verify password first");
        }

        if (checkMfaCode(code)) {
            state = AuthState.FULLY_AUTHENTICATED;
        } else {
            // Fixed: Failed MFA resets to unauthenticated
            state = AuthState.UNAUTHENTICATED;
        }
    }

    public boolean isAuthenticated() {
        // Fixed: Single clear state check
        return state == AuthState.FULLY_AUTHENTICATED;
    }

    public void logout() {
        state = AuthState.UNAUTHENTICATED;
    }
}

CVE Examples

No specific CVEs are listed for this CWE. The vulnerability pattern appears in:

  • Authentication systems with complex state
  • Transaction processing systems
  • Protocol implementations

References

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