diff options
| author | Tim Graham <timograham@gmail.com> | 2016-02-08 14:22:38 -0500 |
|---|---|---|
| committer | Tim Graham <timograham@gmail.com> | 2016-02-22 18:59:23 -0500 |
| commit | 47b5a6a43c400619ca471de02e9f5fcc9f30d8bf (patch) | |
| tree | bc1bd379d54f187c9d756dad998072c086d479a2 /docs | |
| parent | b14470c7b7ee73c328c9c60100165301e6c2e24b (diff) | |
Fixed #26187 -- Removed weak password hashers from PASSWORD_HASHERS.
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/ref/settings.txt | 19 | ||||
| -rw-r--r-- | docs/releases/1.10.txt | 44 | ||||
| -rw-r--r-- | docs/topics/auth/passwords.txt | 65 |
3 files changed, 100 insertions, 28 deletions
diff --git a/docs/ref/settings.txt b/docs/ref/settings.txt index ab710fffac..47024514ca 100644 --- a/docs/ref/settings.txt +++ b/docs/ref/settings.txt @@ -2686,13 +2686,22 @@ Default:: 'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher', 'django.contrib.auth.hashers.BCryptSHA256PasswordHasher', 'django.contrib.auth.hashers.BCryptPasswordHasher', - 'django.contrib.auth.hashers.SHA1PasswordHasher', - 'django.contrib.auth.hashers.MD5PasswordHasher', - 'django.contrib.auth.hashers.UnsaltedSHA1PasswordHasher', - 'django.contrib.auth.hashers.UnsaltedMD5PasswordHasher', - 'django.contrib.auth.hashers.CryptPasswordHasher', ] +.. versionchanged:: 1.10 + + The following hashers were removed from the defaults:: + + 'django.contrib.auth.hashers.SHA1PasswordHasher' + 'django.contrib.auth.hashers.MD5PasswordHasher' + 'django.contrib.auth.hashers.UnsaltedSHA1PasswordHasher' + 'django.contrib.auth.hashers.UnsaltedMD5PasswordHasher' + 'django.contrib.auth.hashers.CryptPasswordHasher' + + Consider using a :ref:`wrapped password hasher <wrapping-password-hashers>` + to strengthen the hashes in your database. If that's not feasible, add this + setting to your project and add back any hashers that you need. + .. setting:: AUTH_PASSWORD_VALIDATORS ``AUTH_PASSWORD_VALIDATORS`` diff --git a/docs/releases/1.10.txt b/docs/releases/1.10.txt index b3f14731d3..db6b730670 100644 --- a/docs/releases/1.10.txt +++ b/docs/releases/1.10.txt @@ -502,6 +502,50 @@ In older versions, assigning ``None`` to a non-nullable ``ForeignKey`` or not allow null values.')``. For consistency with other model fields which don't have a similar check, this check is removed. +Removed weak password hashers from the default ``PASSWORD_HASHERS`` setting +--------------------------------------------------------------------------- + +Django 0.90 stored passwords as unsalted MD5. Django 0.91 added support for +salted SHA1 with automatic upgrade of passwords when a user logs in. Django 1.4 +added PBKDF2 as the default password hasher. + +If you have an old Django project with MD5 or SHA1 (even salted) encoded +passwords, be aware that these can be cracked fairly easily with today's +hardware. To make Django users acknowledge continued use of weak hashers, the +following hashers are removed from the default :setting:`PASSWORD_HASHERS` +setting:: + + 'django.contrib.auth.hashers.SHA1PasswordHasher' + 'django.contrib.auth.hashers.MD5PasswordHasher' + 'django.contrib.auth.hashers.UnsaltedSHA1PasswordHasher' + 'django.contrib.auth.hashers.UnsaltedMD5PasswordHasher' + 'django.contrib.auth.hashers.CryptPasswordHasher' + +Consider using a :ref:`wrapped password hasher <wrapping-password-hashers>` to +strengthen the hashes in your database. If that's not feasible, add the +:setting:`PASSWORD_HASHERS` setting to your project and add back any hashers +that you need. + +You can check if your database has any of the removed hashers like this:: + + from django.contrib.auth import get_user_model + User = get_user_model() + + # Unsalted MD5/SHA1: + User.objects.filter(password__startswith='md5$$') + User.objects.filter(password__startswith='sha1$$') + # Salted MD5/SHA1: + User.objects.filter(password__startswith='md5$').exclude(password__startswith='md5$$') + User.objects.filter(password__startswith='sha1$').exclude(password__startswith='sha1$$') + # Crypt hasher: + User.objects.filter(password__startswith='crypt$$') + + from django.db.models import CharField + from django.db.models.functions import Length + CharField.register_lookup(Length) + # Unsalted MD5 passwords might not have an 'md5$$' prefix: + User.objects.filter(password__length=32) + Miscellaneous ------------- diff --git a/docs/topics/auth/passwords.txt b/docs/topics/auth/passwords.txt index 17d47d8a0b..ecddeddbfa 100644 --- a/docs/topics/auth/passwords.txt +++ b/docs/topics/auth/passwords.txt @@ -62,15 +62,13 @@ The default for :setting:`PASSWORD_HASHERS` is:: 'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher', 'django.contrib.auth.hashers.BCryptSHA256PasswordHasher', 'django.contrib.auth.hashers.BCryptPasswordHasher', - 'django.contrib.auth.hashers.SHA1PasswordHasher', - 'django.contrib.auth.hashers.MD5PasswordHasher', - 'django.contrib.auth.hashers.CryptPasswordHasher', ] -This means that Django will use PBKDF2_ to store all passwords, but will support -checking passwords stored with PBKDF2SHA1, bcrypt_, SHA1_, etc. The next few -sections describe a couple of common ways advanced users may want to modify this -setting. +This means that Django will use PBKDF2_ to store all passwords but will support +checking passwords stored with PBKDF2SHA1 and bcrypt_. + +The next few sections describe a couple of common ways advanced users may want +to modify this setting. .. _bcrypt_usage: @@ -96,13 +94,10 @@ To use Bcrypt as your default storage algorithm, do the following: 'django.contrib.auth.hashers.BCryptPasswordHasher', 'django.contrib.auth.hashers.PBKDF2PasswordHasher', 'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher', - 'django.contrib.auth.hashers.SHA1PasswordHasher', - 'django.contrib.auth.hashers.MD5PasswordHasher', - 'django.contrib.auth.hashers.CryptPasswordHasher', ] - (You need to keep the other entries in this list, or else Django won't - be able to upgrade passwords; see below). + Keep and/or add any entries in this list if you need Django to :ref:`upgrade + passwords <password-upgrades>`. That's it -- now your Django install will use Bcrypt as the default storage algorithm. @@ -168,12 +163,8 @@ default PBKDF2 algorithm: 'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher', 'django.contrib.auth.hashers.BCryptSHA256PasswordHasher', 'django.contrib.auth.hashers.BCryptPasswordHasher', - 'django.contrib.auth.hashers.SHA1PasswordHasher', - 'django.contrib.auth.hashers.MD5PasswordHasher', - 'django.contrib.auth.hashers.CryptPasswordHasher', ] - That's it -- now your Django install will use more iterations when it stores passwords using PBKDF2. @@ -288,6 +279,37 @@ Include any other hashers that your site uses in this list. .. _bcrypt: https://en.wikipedia.org/wiki/Bcrypt .. _`bcrypt library`: https://pypi.python.org/pypi/bcrypt/ +.. _auth-included-hashers: + +Included hashers +---------------- + +The full list of hashers included in Django is:: + + [ + 'django.contrib.auth.hashers.PBKDF2PasswordHasher', + 'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher', + 'django.contrib.auth.hashers.BCryptSHA256PasswordHasher', + 'django.contrib.auth.hashers.BCryptPasswordHasher', + 'django.contrib.auth.hashers.SHA1PasswordHasher', + 'django.contrib.auth.hashers.MD5PasswordHasher', + 'django.contrib.auth.hashers.UnsaltedSHA1PasswordHasher', + 'django.contrib.auth.hashers.UnsaltedMD5PasswordHasher', + 'django.contrib.auth.hashers.CryptPasswordHasher', + ] + +The corresponding algorithm names are: + +* ``pbkdf2_sha256`` +* ``pbkdf2_sha1`` +* ``bcrypt_sha256`` +* ``bcrypt`` +* ``sha1`` +* ``md5`` +* ``unsalted_sha1`` +* ``unsalted_md5`` +* ``crypt`` + Manually managing a user's password =================================== @@ -311,13 +333,10 @@ from the ``User`` model. Creates a hashed password in the format used by this application. It takes one mandatory argument: the password in plain-text. Optionally, you can provide a salt and a hashing algorithm to use, if you don't want to use the - defaults (first entry of ``PASSWORD_HASHERS`` setting). - Currently supported algorithms are: ``'pbkdf2_sha256'``, ``'pbkdf2_sha1'``, - ``'bcrypt_sha256'`` (see :ref:`bcrypt_usage`), ``'bcrypt'``, ``'sha1'``, - ``'md5'``, ``'unsalted_md5'`` (only for backward compatibility) and ``'crypt'`` - if you have the ``crypt`` library installed. If the password argument is - ``None``, an unusable password is returned (a one that will be never - accepted by :func:`check_password`). + defaults (first entry of ``PASSWORD_HASHERS`` setting). See + :ref:`auth-included-hashers` for the algorithm name of each hasher. If the + password argument is ``None``, an unusable password is returned (a one that + will be never accepted by :func:`check_password`). .. function:: is_password_usable(encoded_password) |
