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.
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:
- Default to denying access if any error occurs.
- Implement proper error handling that logs the error without revealing sensitive information.
- 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.