#34661 closed New feature (duplicate)
Peppering user passwords
| Reported by: | Fatih Erikli | Owned by: | nobody |
|---|---|---|---|
| Component: | contrib.auth | Version: | 4.2 |
| Severity: | Normal | Keywords: | |
| Cc: | Triage Stage: | Unreviewed | |
| Has patch: | no | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description (last modified by )
Currently a user's password stored in database in this format:
<algorithm>$<iterations>$<salt>$<hash>
Hash (Last column) is the password hashed with the salt in previous column.
Example, these are two computed passwords, stored on database, for the same password of two users.
pbkdf2_sha256$600000$fb9cUsHWK4EMZ7VWGBAcGD$2uwiVefFwanIhxLrv+/t3sKvP4X6tDKEMw/ysHD5dIc=
pbkdf2_sha256$600000$HgWHWrF2qQD9Owj4XeEkjY$rh0qzfo+/ZCzWbL9ZJa8aKhiO5xoEMfT4EtP/+A+LzI=
The password is 123456.
Imagine I am an attacker, who got the database of different django project, I want to look up the users who have chosen the password 123456.
I have the salts of users stored in database.
make_password('123456', 'fb9cUsHWK4EMZ7VWGBAcGD')
pbkdf2_sha256$600000$fb9cUsHWK4EMZ7VWGBAcGD$2uwiVefFwanIhxLrv+/t3sKvP4X6tDKEMw/ysHD5dIc=
make_password('123456', 'HgWHWrF2qQD9Owj4XeEkjY')
pbkdf2_sha256$600000$HgWHWrF2qQD9Owj4XeEkjY$rh0qzfo+/ZCzWbL9ZJa8aKhiO5xoEMfT4EtP/+A+LzI=
These are correct password combinations. I am able to lookup the users who have their passwords exposed in public.
Password 123456 is not a possible case in Django, since the password fields have a complexity validation. However, the salt is available to the attacker when a database is stolen. Salt could be used
- to hash the raw password pair in a rainbow table.
- to hash the already exposed passwords.
There is one more element needed for hashing the password, pepper, should be project specific. When a database is exposed in public, the attacker will not be able to lookup the passwords, since they don't have the secret pepper key.
I am not sure about the vulnerability enumeration, but CWE-760 seems closer. Salt is not weak, but it is known. The salt is stored next to the hashed password.
This is a case of when a database is stolen, however I think Django, by default, should do everything that could be done at the framework level to keep the user information secured.
Change History (14)
comment:1 by , 2 years ago
| Description: | modified (diff) |
|---|
comment:2 by , 2 years ago
| Description: | modified (diff) |
|---|
comment:3 by , 2 years ago
| Description: | modified (diff) |
|---|
comment:4 by , 2 years ago
| Description: | modified (diff) |
|---|
comment:5 by , 2 years ago
| Description: | modified (diff) |
|---|
comment:6 by , 2 years ago
| Description: | modified (diff) |
|---|
comment:7 by , 2 years ago
| Description: | modified (diff) |
|---|
comment:9 by , 2 years ago
| Description: | modified (diff) |
|---|
comment:10 by , 2 years ago
| Description: | modified (diff) |
|---|
comment:11 by , 2 years ago
| Description: | modified (diff) |
|---|
comment:12 by , 2 years ago
| Description: | modified (diff) |
|---|
comment:14 by , 2 years ago
| Type: | Uncategorized → New feature |
|---|
Here is an example hasher:
# yourapp.hashers.py class PepperedPBKDF2PasswordHasher(PBKDF2PasswordHasher): algorithm = "pepperred_pbkdf2_sha256" def encode(self, password, salt, iterations=None): iterations = iterations or self.iterations hash = pbkdf2(password, salt, iterations, digest=self.digest) hash = base64.b64encode( hash+settings.PASSWORD_PEPPER).decode('ascii').strip() return "%s$%d$%s$%s" % (self.algorithm, iterations, salt, hash)In settings:
PASSWORD_PEPPER = b'4545randombytes342445' PASSWORD_HASHERS = [ "yourapp.hashers.PepperedPBKDF2PasswordHasher", "django.contrib.auth.hashers.PBKDF2PasswordHasher", "django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher", "django.contrib.auth.hashers.Argon2PasswordHasher", "django.contrib.auth.hashers.BCryptSHA256PasswordHasher", "django.contrib.auth.hashers.ScryptPasswordHasher", ]Passwords will continue working when the last (first in the list) hasher is added. The passwords will break when a pepper is changed.