CWE-636: Not Failing Securely ('Failing Open')

Learn about CWE-636 (Not Failing Securely ('Failing Open')), its security impact, exploitation methods, and prevention guidelines.

What is Not Failing Securely ('Failing Open')?

• Overview: When a software product encounters an error or failure, CWE-636 occurs when it defaults to a less secure state, such as using weaker encryption or more permissive access controls, rather than maintaining or transitioning to a more secure state. This is known as "failing open" rather than "failing safe."

• Exploitation Methods:

  • Attackers can exploit this vulnerability by intentionally causing errors or failures that push the system into the less secure state.
  • Common attack patterns include triggering exceptions or input errors that lead to fallback mechanisms activating weaker security protocols.

• Security Impact:

  • Direct consequences include unauthorized access or exposure of sensitive data due to relaxed security measures.
  • Potential cascading effects might involve further system compromise or lateral movement within the network.
  • Business impact can include loss of customer trust, legal liability, and potential financial losses due to data breaches.

• Prevention Guidelines:

  • Specific code-level fixes include ensuring that error handling mechanisms maintain the highest security posture even in failure states.
  • Security best practices involve implementing a "fail-safe" or "fail-secure" approach, where systems default to the most secure state possible.
  • Recommended tools and frameworks include using error handling libraries and security frameworks that are designed to enforce secure failure configurations.
Corgea can automatically detect and fix Not Failing Securely ('Failing Open') in your codebase. [Try Corgea free today](https://corgea.app).

Technical Details

Likelihood of Exploit: Not specified

Affected Languages: Not Language-Specific

Affected Technologies: Not Technology-Specific, ICS/OT

Vulnerable Code Example

import hashlib

def authenticate_user(username, password):
    # Simulating a database lookup
    stored_password_hash = get_stored_password_hash(username)
    if not stored_password_hash:
        # If user not found, fail open by allowing access
        return True

    # Hash the provided password for comparison
    password_hash = hashlib.sha256(password.encode()).hexdigest()
    
    # Check if the hashed password matches the stored hash
    if password_hash == stored_password_hash:
        return True
    else:
        # In case of an error, fail open by allowing access
        return True

def get_stored_password_hash(username):
    # This function should fetch the password hash from a database
    # Here we simulate a missing user scenario
    return None

How to fix Not Failing Securely ('Failing Open')?

In the above code, the system is designed to "fail open," which means that if there is an error (e.g., user not found or incorrect password), it incorrectly grants access. This is a critical security flaw because it allows unauthorized access when the system should deny it.

To fix this issue, we should ensure that the system "fails closed." This means that access is denied by default unless explicitly granted based on correct credentials. Additionally, we should handle exceptions and errors gracefully to maintain security.

Key Fix Steps:

  1. Default to denying access if any error occurs.
  2. Implement proper error handling that logs the error without revealing sensitive information.
  3. Ensure that the logic correctly checks for user existence before proceeding to password verification.

Fixed Code Example

import hashlib

def authenticate_user(username, password):
    # Simulating a database lookup
    stored_password_hash = get_stored_password_hash(username)
    if not stored_password_hash:
        # If user not found, fail closed by denying access
        return False

    try:
        # Hash the provided password for comparison
        password_hash = hashlib.sha256(password.encode()).hexdigest()
        
        # Check if the hashed password matches the stored hash
        if password_hash == stored_password_hash:
            return True
        else:
            return False
    except Exception as e:
        log_error(f"Authentication error for user {username}: {str(e)}")
        # Fail closed by denying access on error
        return False

def get_stored_password_hash(username):
    # This function should fetch the password hash from a database
    # Here we simulate a missing user scenario
    return None

def log_error(message):
    # A placeholder function to log errors
    # In a real-world application, this should log to a secure location
    print(f"Error: {message}")

In the fixed code, the system denies access by default when encountering errors or invalid credentials. We have added error logging to capture issues without providing unauthorized access. This ensures that the system remains secure and robust against unauthorized access attempts.

Corgea Logo

Find this vulnerability and fix it with Corgea

Scan your codebase for CWE-636: Not Failing Securely ('Failing Open') and get remediation guidance

Start for free and no credit card needed.