CWE-257: Storing Passwords in a Recoverable Format
Learn about CWE-257 (Storing Passwords in a Recoverable Format), its security impact, exploitation methods, and prevention guidelines.
What is Storing Passwords in a Recoverable Format?
• Overview: Storing passwords in a recoverable format means that the passwords can be retrieved in their original form, making them vulnerable to unauthorized access and misuse by both external attackers and internal personnel.
• Exploitation Methods:
- Attackers can exploit this vulnerability by accessing stored passwords through database breaches or insider threats.
- Common attack patterns include brute force attacks and social engineering to gain access to the stored password data.
• Security Impact:
- Direct consequences include unauthorized access to user accounts and sensitive information.
- Potential cascading effects involve the compromise of multiple systems if the same password is reused across different platforms.
- Business impact includes loss of customer trust, potential legal liabilities, and financial losses due to data breaches.
• Prevention Guidelines:
- Use strong, one-way hashing algorithms (e.g., bcrypt, Argon2, or PBKDF2) to store passwords instead of reversible encryption or plaintext.
- Implement security best practices such as salting passwords and enforcing strong password policies.
- Recommended tools and frameworks include libraries for secure password hashing and storage, such as the OWASP Password Storage Cheat Sheet, to guide secure implementation.
Technical Details
Likelihood of Exploit:
Affected Languages: Not Language-Specific
Affected Technologies: Not specified
Vulnerable Code Example
Python Example
import sqlite3
def store_password(username, password):
# Vulnerably storing password in plaintext
conn = sqlite3.connect('users.db')
cursor = conn.cursor()
cursor.execute("INSERT INTO users (username, password) VALUES (?, ?)", (username, password))
conn.commit()
conn.close()
Explanation of Vulnerability
- Storing Passwords in Plaintext: This code stores user passwords directly in plaintext within a database. This is a significant security risk because if the database is compromised, an attacker can easily access all user passwords. Plaintext storage does not protect the password from unauthorized access.
How to fix Storing Passwords in a Recoverable Format?
To fix this vulnerability, passwords should be stored in a non-recoverable format. This is generally done by hashing passwords with a strong, one-way cryptographic hash function. Additionally, a unique salt should be used for each password to protect against rainbow table attacks. In Python, the bcrypt
library is a popular choice for securely hashing passwords.
Best Practices for Password Storage
- Hash Passwords: Use a reliable hashing algorithm such as bcrypt to hash passwords.
- Use a Salt: Ensure each password is hashed with a unique salt to make pre-computed attacks (like rainbow tables) infeasible.
- Secure Hashing Parameters: Choose appropriate parameters for the hashing function to balance security and performance.
Fixed Code Example
import sqlite3
import bcrypt
def store_password(username, password):
# Securely hashing the password with bcrypt
salt = bcrypt.gensalt() # Generate a unique salt
hashed_password = bcrypt.hashpw(password.encode('utf-8'), salt)
conn = sqlite3.connect('users.db')
cursor = conn.cursor()
cursor.execute("INSERT INTO users (username, password) VALUES (?, ?)", (username, hashed_password))
conn.commit()
conn.close()
Explanation of Fix
- bcrypt Library: Used to securely hash passwords.
bcrypt
provides both a hashing function and a way to generate a secure salt. - Hashing with Salt: The password is hashed using
bcrypt.hashpw()
, which combines the password with a generated salt. This ensures that even if two users have the same password, their hashed passwords will differ due to unique salts. - Storing Hashed Passwords: The hashed password is stored in the database, ensuring that even if the database is compromised, the original passwords cannot be easily retrieved. This approach protects user passwords from being exposed in the event of a data breach.
By implementing these changes, passwords are stored securely in a manner that makes it impractical for an attacker to reverse-engineer the original passwords from the stored hashes.