CWE-836: Use of Password Hash Instead of Password for Authentication
Learn about CWE-836 (Use of Password Hash Instead of Password for Authentication), its security impact, exploitation methods, and prevention guidelines.
What is Use of Password Hash Instead of Password for Authentication?
• Overview: Use of Password Hash Instead of Password for Authentication (CWE-836) occurs when a system relies on the client to generate a password hash, which is then compared to a stored hash on the server, potentially allowing attackers to authenticate without the actual password.
• Exploitation Methods:
- Attackers can exploit this vulnerability by obtaining the password hash through methods such as SQL injection or information exposure.
- Common attack patterns include hash replay attacks, where attackers use a modified client to send the stolen hash, bypassing the need to know the actual password.
• Security Impact:
- Direct consequences of successful exploitation include unauthorized access to accounts or systems.
- Potential cascading effects could involve further data breaches or lateral movement within the network.
- Business impact might include loss of customer trust, financial losses, and legal implications due to compromised data security.
• Prevention Guidelines:
- Specific code-level fixes include ensuring that password hashing is done server-side, not client-side.
- Security best practices involve using secure communication protocols (e.g., HTTPS) to protect data in transit and applying additional authentication factors (e.g., multi-factor authentication).
- Recommended tools and frameworks include using libraries that handle password hashing securely, such as bcrypt or Argon2, and implementing secure password storage and verification mechanisms.
Technical Details
Likelihood of Exploit: Not specified
Affected Languages: Not Language-Specific
Affected Technologies: Not specified
Vulnerable Code Example
import hashlib
def authenticate_user(stored_hash, received_hash):
"""
Vulnerable function: This function compares a received hash directly with the stored hash.
This assumes the client is sending a hash of the password, which exposes the system to replay attacks.
"""
# Compare the received password hash with the stored password hash
return stored_hash == received_hash
Explanation:
- Line 3-6: The function
authenticate_user
takes astored_hash
and areceived_hash
as parameters. This design flaw assumes the client sends a hash of the password, which can be exploited by an attacker who sends a precomputed hash directly, bypassing the need to know the actual password. This approach is vulnerable to replay attacks.
How to fix Use of Password Hash Instead of Password for Authentication?
The vulnerability arises from directly comparing hashes received from the client with stored password hashes. This approach is insecure because it assumes that the client can be trusted to generate the hash correctly and securely. Instead, the client could send a precomputed hash that matches the stored hash, bypassing the need for knowing the actual password.
Correct Approach:
- Do not send password hashes from the client: Always send the raw password over a secure channel (e.g., HTTPS) and compute the hash server-side.
- Use a strong password hashing algorithm: Use algorithms like bcrypt, Argon2, or PBKDF2, which are designed to be slow and resist brute-force attacks.
- Salting and hashing: Always salt and hash passwords before storing them in the database to prevent the use of rainbow tables.
- Secure communication: Ensure that all communications between client and server are encrypted using TLS/SSL to prevent interception of passwords.
Fixed Code Example
import bcrypt
def authenticate_user(stored_hash, password):
"""
Fixed function: This function now takes the raw password and hashes it server-side,
comparing it securely with the stored hash.
"""
# Hash the received password with bcrypt and compare it to the stored hash
# bcrypt automatically handles the salt internally
return bcrypt.checkpw(password.encode('utf-8'), stored_hash.encode('utf-8'))
Explanation:
- Line 3: Importing
bcrypt
, a library specifically designed for secure password hashing. - Line 6-10: The function
authenticate_user
now expects a raw password input instead of a hash. Thebcrypt.checkpw()
function securely compares the plaintext password against the stored hash. It automatically handles salting and hashing, ensuring that the authentication process is secure. This prevents the client from sending precomputed hashes and mitigates the risk of replay attacks.