Weak Cryptography for Passwords
Summary
Passwords are hashed with an algorithm not designed for password storage - a fast general-purpose hash (MD5, SHA-1, unsalted SHA-256) instead of a purpose-built, deliberately slow password-hashing function (bcrypt, scrypt, Argon2). Fast hashes are exactly the wrong property for password storage: they let an attacker who obtains the hash database run billions of guesses per second on commodity GPU hardware, where a properly slow, memory-hard hash would limit that same attacker to a few thousand.
Why This Requires More Than a Black-Box Scan
Which hashing algorithm protects stored passwords is an internal implementation detail - not observable from outside the application at all, since a login form behaves identically to an external observer regardless of what hash function sits behind it.
Where This Is Actually Caught
Source-level review of the password-storage and verification code, checking the hashing library and parameters against current recommendations (Argon2id being the modern default recommendation).
Tip: This is almost always found through code or configuration review of the actual storage and hashing implementation, rather than through any external test — the stored value looks the same from outside regardless of whether it's properly hashed, so the only reliable check is reading the code that produces it.
Real-World Impact
Real-World Impact
How passwords are stored determines the entire blast radius of a future database breach. Plaintext storage or a recoverable ("encrypted, not hashed") format means a single database compromise hands over every user's actual password immediately, with no cracking effort required at all. Weak hashing, a fast general-purpose hash without a per-user salt, or an outdated algorithm, means the same breach still requires attacker effort, but often not very much: modern GPU-based cracking makes short work of unsalted or fast-hashed password databases at scale.
Because of widespread password reuse across services, the damage from a poorly-stored password database extends well beyond the breached application itself — leaked credentials get tested ("credential stuffed") against banking, email, and other higher-value targets, which is why this class is treated as high-severity even when the breached application itself holds low-value data.
Insufficiently random values in adjacent systems, password-reset tokens, session identifiers generated with a weak or predictable source, compound the same underlying risk: even a properly-hashed password becomes irrelevant if the reset flow around it can be predicted instead.
Prevention & Remediation
Prevention and Secure Design
Preventing Weak Cryptography for Passwords takes a defense-in-depth approach — no single control below is sufficient alone, but together they close off both the primary path and the most common bypasses.
Hash with a modern, purpose-built algorithm. Use bcrypt, scrypt, or Argon2 with a per-user salt — never plaintext, never reversible encryption, and never an unsalted or fast general-purpose hash like unsalted SHA-256/MD5.
Never store recoverable passwords, even for legitimate-sounding reasons. A "recoverable" format exists so support can retrieve a forgotten password directly — the correct flow is always a reset, not a retrieval, and that distinction alone prevents this class.
Use a cryptographically secure random source for anything security-relevant. Password-reset tokens, session identifiers, and similar values need to come from a CSPRNG, not a general-purpose or predictable random function.
Rate-limit and expire reset tokens tightly. Even a well-generated reset token should have a short expiry and single-use enforcement, so a leaked or predicted token has a narrow window of usefulness.
Plan for algorithm migration. Hashing recommendations shift over time (work-factor increases, algorithm deprecation) — build the storage schema to support re-hashing on next login rather than assuming today's choice is permanent.