| name | weak-password-hashing-anti-pattern |
| description | Security anti-pattern for weak password hashing (CWE-327, CWE-759). Use when generating or reviewing code that stores or verifies user passwords. Detects use of MD5, SHA1, SHA256 without salt, or missing password hashing entirely. Recommends bcrypt, Argon2, or scrypt. |
Weak Password Hashing Anti-Pattern
Severity: High
Summary
Applications use fast general-purpose hash functions (MD5, SHA-1, SHA-256) without salting for password storage, enabling rapid cracking via rainbow tables or GPU-accelerated brute-force (billions of hashes per second). Results in mass account compromise and credential stuffing attacks.
The Anti-Pattern
The anti-pattern is using cryptographic hash functions that are too fast or lack essential features like salting and adjustable work factors, making them vulnerable to offline attacks.
BAD Code Example
import hashlib
def hash_password_md5(password):
return hashlib.md5(password.encode()).hexdigest()
def verify_password_md5(password, stored_hash):
return hash_password_md5(password) == stored_hash
def hash_password_sha256_unsalted(password):
return hashlib.sha256(password.encode()).hexdigest()
GOOD Code Example
import bcrypt
def hash_password_secure(password):
hashed_password = bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt(rounds=12))
return hashed_password.decode('utf-8')
def verify_password_secure(password, stored_hash):
return bcrypt.checkpw(password.encode('utf-8'), stored_hash.encode('utf-8'))
Detection
- Code Review: Search your codebase for password hashing implementations.
- Look for
hashlib.md5(), hashlib.sha1(), or hashlib.sha256() being used for passwords.
- Check if
bcrypt, argon2, or scrypt libraries are used.
- Verify that a unique, cryptographically secure salt is generated for each password.
- Database Inspection: Look at the
password or password_hash column in your user database.
- Are the hashes all of the same length and format? (Suggests no salt or static salt).
- Do they start with prefixes like
$2a$ (bcrypt), $argon2id$ (Argon2), or $s2$ (scrypt)?
- Check for plaintext passwords: Ensure that passwords are never stored in plaintext.
Prevention
Related Security Patterns & Anti-Patterns
References