summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authorTim Graham <timograham@gmail.com>2016-02-08 14:22:38 -0500
committerTim Graham <timograham@gmail.com>2016-02-22 18:59:23 -0500
commit47b5a6a43c400619ca471de02e9f5fcc9f30d8bf (patch)
treebc1bd379d54f187c9d756dad998072c086d479a2 /docs
parentb14470c7b7ee73c328c9c60100165301e6c2e24b (diff)
Fixed #26187 -- Removed weak password hashers from PASSWORD_HASHERS.
Diffstat (limited to 'docs')
-rw-r--r--docs/ref/settings.txt19
-rw-r--r--docs/releases/1.10.txt44
-rw-r--r--docs/topics/auth/passwords.txt65
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)