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
| Impact | Details |
|---|---|
| Integrity | Scope: Integrity Operations execute with wrong assumptions about system state, causing incorrect behavior. |
| Other | Scope: 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
- MITRE Corporation. "CWE-372: Incomplete Internal State Distinction." https://cwe.mitre.org/data/definitions/372.html