summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authorFlorian Apolloner <florian@apolloner.eu>2016-02-13 21:09:46 +0100
committerTim Graham <timograham@gmail.com>2016-03-01 11:38:49 -0500
commitaf7d09b0c5c6ab68e629fd9baf736f9dd203b18e (patch)
treeb3d0cb7460ab41b7679cfea993389dd0535337e1 /docs
parentfc6d147a63f89795dbcdecb0559256470fff4380 (diff)
[1.9.x] Fixed CVE-2016-2513 -- Fixed user enumeration timing attack during login.
This is a security fix.
Diffstat (limited to 'docs')
-rw-r--r--docs/releases/1.8.10.txt33
-rw-r--r--docs/releases/1.9.3.txt33
-rw-r--r--docs/topics/auth/passwords.txt31
3 files changed, 97 insertions, 0 deletions
diff --git a/docs/releases/1.8.10.txt b/docs/releases/1.8.10.txt
index 73c7cc04a4..d57afc470d 100644
--- a/docs/releases/1.8.10.txt
+++ b/docs/releases/1.8.10.txt
@@ -22,6 +22,39 @@ redirecting to this URL sends the user to ``attacker.com``.
Also, if a developer relies on ``is_safe_url()`` to provide safe redirect
targets and puts such a URL into a link, they could suffer from an XSS attack.
+CVE-2016-2513: User enumeration through timing difference on password hasher work factor upgrade
+================================================================================================
+
+In each major version of Django since 1.6, the default number of iterations for
+the ``PBKDF2PasswordHasher`` and its subclasses has increased. This improves
+the security of the password as the speed of hardware increases, however, it
+also creates a timing difference between a login request for a user with a
+password encoded in an older number of iterations and login request for a
+nonexistent user (which runs the default hasher's default number of iterations
+since Django 1.6).
+
+This only affects users who haven't logged in since the iterations were
+increased. The first time a user logs in after an iterations increase, their
+password is updated with the new iterations and there is no longer a timing
+difference.
+
+The new ``BasePasswordHasher.harden_runtime()`` method allows hashers to bridge
+the runtime gap between the work factor (e.g. iterations) supplied in existing
+encoded passwords and the default work factor of the hasher. This method
+is implemented for ``PBKDF2PasswordHasher`` and ``BCryptPasswordHasher``.
+The number of rounds for the latter hasher hasn't changed since Django 1.4, but
+some projects may subclass it and increase the work factor as needed.
+
+A warning will be emitted for any :ref:`third-party password hashers that don't
+implement <write-your-own-password-hasher>` a ``harden_runtime()`` method.
+
+If you have different password hashes in your database (such as SHA1 hashes
+from users who haven't logged in since the default hasher switched to PBKDF2
+in Django 1.4), the timing difference on a login request for these users may be
+even greater and this fix doesn't remedy that difference (or any difference
+when changing hashers). You may be able to :ref:`upgrade those hashes
+<wrapping-password-hashers>` to prevent a timing attack for that case.
+
Bugfixes
========
diff --git a/docs/releases/1.9.3.txt b/docs/releases/1.9.3.txt
index 056122b16e..355eaf96e9 100644
--- a/docs/releases/1.9.3.txt
+++ b/docs/releases/1.9.3.txt
@@ -22,6 +22,39 @@ redirecting to this URL sends the user to ``attacker.com``.
Also, if a developer relies on ``is_safe_url()`` to provide safe redirect
targets and puts such a URL into a link, they could suffer from an XSS attack.
+CVE-2016-2513: User enumeration through timing difference on password hasher work factor upgrade
+================================================================================================
+
+In each major version of Django since 1.6, the default number of iterations for
+the ``PBKDF2PasswordHasher`` and its subclasses has increased. This improves
+the security of the password as the speed of hardware increases, however, it
+also creates a timing difference between a login request for a user with a
+password encoded in an older number of iterations and login request for a
+nonexistent user (which runs the default hasher's default number of iterations
+since Django 1.6).
+
+This only affects users who haven't logged in since the iterations were
+increased. The first time a user logs in after an iterations increase, their
+password is updated with the new iterations and there is no longer a timing
+difference.
+
+The new ``BasePasswordHasher.harden_runtime()`` method allows hashers to bridge
+the runtime gap between the work factor (e.g. iterations) supplied in existing
+encoded passwords and the default work factor of the hasher. This method
+is implemented for ``PBKDF2PasswordHasher`` and ``BCryptPasswordHasher``.
+The number of rounds for the latter hasher hasn't changed since Django 1.4, but
+some projects may subclass it and increase the work factor as needed.
+
+A warning will be emitted for any :ref:`third-party password hashers that don't
+implement <write-your-own-password-hasher>` a ``harden_runtime()`` method.
+
+If you have different password hashes in your database (such as SHA1 hashes
+from users who haven't logged in since the default hasher switched to PBKDF2
+in Django 1.4), the timing difference on a login request for these users may be
+even greater and this fix doesn't remedy that difference (or any difference
+when changing hashers). You may be able to :ref:`upgrade those hashes
+<wrapping-password-hashers>` to prevent a timing attack for that case.
+
Bugfixes
========
diff --git a/docs/topics/auth/passwords.txt b/docs/topics/auth/passwords.txt
index 17d47d8a0b..2da25ecf6c 100644
--- a/docs/topics/auth/passwords.txt
+++ b/docs/topics/auth/passwords.txt
@@ -195,6 +195,14 @@ unmentioned algorithms won't be able to upgrade. Hashed passwords will be
updated when increasing (or decreasing) the number of PBKDF2 iterations or
bcrypt rounds.
+Be aware that if all the passwords in your database aren't encoded in the
+default hasher's algorithm, you may be vulnerable to a user enumeration timing
+attack due to a difference between the duration of a login request for a user
+with a password encoded in a non-default algorithm and the duration of a login
+request for a nonexistent user (which runs the default hasher). You may be able
+to mitigate this by :ref:`upgrading older password hashes
+<wrapping-password-hashers>`.
+
.. versionchanged:: 1.9
Passwords updates when changing the number of bcrypt rounds was added.
@@ -288,6 +296,29 @@ 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/
+.. _write-your-own-password-hasher:
+
+Writing your own hasher
+-----------------------
+
+.. versionadded:: 1.9.3
+
+If you write your own password hasher that contains a work factor such as a
+number of iterations, you should implement a
+``harden_runtime(self, password, encoded)`` method to bridge the runtime gap
+between the work factor supplied in the ``encoded`` password and the default
+work factor of the hasher. This prevents a user enumeration timing attack due
+to difference between a login request for a user with a password encoded in an
+older number of iterations and a nonexistent user (which runs the default
+hasher's default number of iterations).
+
+Taking PBKDF2 as example, if ``encoded`` contains 20,000 iterations and the
+hasher's default ``iterations`` is 30,000, the method should run ``password``
+through another 10,000 iterations of PBKDF2.
+
+If your hasher doesn't have a work factor, implement the method as a no-op
+(``pass``).
+
Manually managing a user's password
===================================