Unsafe password storage or use of fast hashes

Unsafe password storage or use of fast hashes

Description

Storing passwords in plaintext or with a fast general-purpose hash such as MD5 or SHA makes leaked data vulnerable to offline password guessing.

Potential impact

  • A database or log leak can increase the risk of account takeover.
  • Fast hashes are particularly vulnerable to GPU-based guessing.

Remediation

  • Use a dedicated password-hashing algorithm with an adjustable cost, such as bcrypt, scrypt, Argon2id or PBKDF2.
  • Gradually replace existing fast hashes by rehashing the password after a successful login.

Examples

These excerpts compare password storage only. Benchmark the bcrypt cost in the deployment environment, and handle inputs longer than 72 bytes as errors.

Before

go
user.SetPasswordHash(sha256.Sum256([]byte(password)))

After

go
package example

import "golang.org/x/crypto/bcrypt"

type passwordHashStore interface {
    SetPasswordHash([]byte)
}

func storePassword(user passwordHashStore, password string) error {
    hash, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
    if err != nil {
        return err
    }
    user.SetPasswordHash(hash)
    return nil
}

Explanation:

  • Before: Plaintext storage directly exposes passwords. Fast SHA/MD5 hashes let attackers test many guesses offline after a database or log leak.
  • After: A configurable bcrypt cost makes offline guessing more expensive. Checking the hash-generation error prevents storing a nil or invalid hash when the password is too long or another error occurs.

References