Weak password hashing

Password hashing with insufficient computational effort

Description

Applying a fast general-purpose hash directly to a password lets an attacker test many guesses quickly against a leaked hash. Weak or reused passwords are especially vulnerable to being recovered this way.

Potential impact

  • Password cracking: Fast hashing makes large numbers of password guesses inexpensive.
  • Account takeover: Recovered passwords may allow attackers to access accounts.
  • Information disclosure: Compromised accounts may expose sensitive system data.

Remediation

  • Use a dedicated password-hashing algorithm such as Argon2id, bcrypt, scrypt, or PBKDF2 with an adequate iteration count.
  • Distinguish general hashes from password hashes. SHA-256 is useful for file or message integrity checks but is too fast to use directly for password storage.
  • Use a vetted library that manages random per-password salts, and benchmark cost parameters in the production environment.
  • Follow current security guidance from sources such as OWASP and NIST.

Examples

Password hashing

Before

MD5:

python
# Unsafe password hashing with MD5
import hashlib

password = b'mypassword'
hashed_password = hashlib.md5(password).hexdigest()

SHA-1:

python
# Unsafe password hashing with SHA-1
import hashlib

password = "mypassword"
hashed_password = hashlib.sha1(password.encode()).hexdigest()

After

Bcrypt:

python
# Safe password hashing with bcrypt
import bcrypt

def hash_password(password):
    salt = bcrypt.gensalt(rounds=12)
    hashed = bcrypt.hashpw(password.encode(), salt)
    return hashed

password = "mysecretpassword"
hashed_password = hash_password(password)

Argon2:

python
# Safe password hashing with Argon2
from argon2 import PasswordHasher

def hash_password(password):
    ph = PasswordHasher()
    return ph.hash(password)

password = "mysecretpassword"
hashed_password = hash_password(password)

General data integrity hashing, not password hashing

python
# Use SHA-256 for general data integrity, not for passwords
import hashlib

document = b'document contents'
document_digest = hashlib.sha256(document).hexdigest()

Explanation:

  • Before: MD5 and SHA-1 are unsuitable for password storage. Applying fast general hashes such as SHA-256, SHA-512, or SHA-3 directly to passwords also makes offline guessing inexpensive.
  • After: Use dedicated algorithms such as bcrypt or Argon2id with adjustable cost and per-password salts. The SHA-256 example is only for general data integrity, not for passwords.

References