1
0
mirror of https://github.com/django/django.git synced 2025-10-23 21:59:11 +00:00

Fixed #32800 -- Changed CsrfViewMiddleware not to mask the CSRF secret.

This also adds CSRF_COOKIE_MASKED transitional setting helpful in
migrating multiple instance of the same project to Django 4.1+.

Thanks Florian Apolloner and Shai Berger for reviews.

Co-Authored-By: Mariusz Felisiak <felisiak.mariusz@gmail.com>
This commit is contained in:
Chris Jerdonek
2021-08-17 09:13:13 -04:00
committed by Mariusz Felisiak
parent 05e29da421
commit 5d80843ebc
10 changed files with 284 additions and 143 deletions

View File

@@ -67,6 +67,8 @@ details on these changes.
* The ``SitemapIndexItem.__str__()`` method will be removed.
* The ``CSRF_COOKIE_MASKED`` transitional setting will be removed.
.. _deprecation-removed-in-4.1:
4.1

View File

@@ -110,11 +110,12 @@ The above code could be simplified by using the `JavaScript Cookie library
.. note::
The CSRF token is also present in the DOM, but only if explicitly included
using :ttag:`csrf_token` in a template. The cookie contains the canonical
token; the ``CsrfViewMiddleware`` will prefer the cookie to the token in
the DOM. Regardless, you're guaranteed to have the cookie if the token is
present in the DOM, so you should use the cookie!
The CSRF token is also present in the DOM in a masked form, but only if
explicitly included using :ttag:`csrf_token` in a template. The cookie
contains the canonical, unmasked token. The
:class:`~django.middleware.csrf.CsrfViewMiddleware` will accept either.
However, in order to protect against `BREACH`_ attacks, it's recommended to
use a masked token.
.. warning::
@@ -231,25 +232,21 @@ How it works
The CSRF protection is based on the following things:
#. A CSRF cookie that is based on a random secret value, which other sites
will not have access to.
#. A CSRF cookie that is a random secret value, which other sites will not have
access to.
This cookie is set by ``CsrfViewMiddleware``. It is sent with every
response that has called ``django.middleware.csrf.get_token()`` (the
function used internally to retrieve the CSRF token), if it wasn't already
set on the request.
``CsrfViewMiddleware`` sends this cookie with the response whenever
``django.middleware.csrf.get_token()`` is called. It can also send it in
other cases. For security reasons, the value of the secret is changed each
time a user logs in.
In order to protect against `BREACH`_ attacks, the token is not simply the
secret; a random mask is prepended to the secret and used to scramble it.
#. A hidden form field with the name 'csrfmiddlewaretoken', present in all
outgoing POST forms.
For security reasons, the value of the secret is changed each time a
user logs in.
#. A hidden form field with the name 'csrfmiddlewaretoken' present in all
outgoing POST forms. The value of this field is, again, the value of the
secret, with a mask which is both added to it and used to scramble it. The
mask is regenerated on every call to ``get_token()`` so that the form field
value is changed in every such response.
In order to protect against `BREACH`_ attacks, the value of this field is
not simply the secret. It is scrambled differently with each response using
a mask. The mask is generated randomly on every call to ``get_token()``, so
the form field value is different each time.
This part is done by the template tag.
@@ -294,6 +291,10 @@ The CSRF protection is based on the following things:
``Origin`` checking was added, as described above.
.. versionchanged:: 4.1
In older versions, the CSRF cookie value was masked.
This ensures that only forms that have originated from trusted domains can be
used to POST data back.

View File

@@ -347,6 +347,22 @@ form input <acquiring-csrf-token-from-html>` instead of :ref:`from the cookie
See :setting:`SESSION_COOKIE_HTTPONLY` for details on ``HttpOnly``.
.. setting:: CSRF_COOKIE_MASKED
``CSRF_COOKIE_MASKED``
----------------------
.. versionadded:: 4.1
Default: ``False``
Whether to mask the CSRF cookie. See
:ref:`release notes <csrf-cookie-masked-usage>` for usage details.
.. deprecated:: 4.1
This transitional setting is deprecated and will be removed in Django 5.0.
.. setting:: CSRF_COOKIE_NAME
``CSRF_COOKIE_NAME``

View File

@@ -26,6 +26,25 @@ officially support the latest release of each series.
What's new in Django 4.1
========================
.. _csrf-cookie-masked-usage:
``CSRF_COOKIE_MASKED`` setting
------------------------------
The new :setting:`CSRF_COOKIE_MASKED` transitional setting allows specifying
whether to mask the CSRF cookie.
:class:`~django.middleware.csrf.CsrfViewMiddleware` no longer masks the CSRF
cookie like it does the CSRF token in the DOM. If you are upgrading multiple
instances of the same project to Django 4.1, you should set
:setting:`CSRF_COOKIE_MASKED` to ``True`` during the transition, in
order to allow compatibility with the older versions of Django. Once the
transition to 4.1 is complete you can stop overriding
:setting:`CSRF_COOKIE_MASKED`.
This setting is deprecated as of this release and will be removed in Django
5.0.
Minor features
--------------
@@ -270,6 +289,13 @@ Miscellaneous
* The Django test runner now returns a non-zero error code for unexpected
successes from tests marked with :py:func:`unittest.expectedFailure`.
* :class:`~django.middleware.csrf.CsrfViewMiddleware` no longer masks the CSRF
cookie like it does the CSRF token in the DOM.
* :class:`~django.middleware.csrf.CsrfViewMiddleware` now uses
``request.META['CSRF_COOKIE']`` for storing the unmasked CSRF secret rather
than a masked version. This is an undocumented, private API.
.. _deprecated-features-4.1:
Features deprecated in 4.1
@@ -283,6 +309,8 @@ Miscellaneous
:ref:`context variables <sitemap-index-context-variables>`, expecting a list
of objects with ``location`` and optional ``lastmod`` attributes.
* ``CSRF_COOKIE_MASKED`` transitional setting is deprecated.
Features removed in 4.1
=======================