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,Argon2idor 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
nilor invalid hash when the password is too long or another error occurs.