Commit ab26b65b authored by Joshua Kehn's avatar Joshua Kehn Committed by Tim Graham
Browse files

Fixed #25334 -- Provided a way to allow cross-origin unsafe requests over HTTPS.

Added the CSRF_TRUSTED_ORIGINS setting which contains a list of other
domains that are included during the CSRF Referer header verification
for secure (HTTPS) requests.
parent 48c420d9
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -558,6 +558,7 @@ CSRF_COOKIE_PATH = '/'
CSRF_COOKIE_SECURE = False
CSRF_COOKIE_HTTPONLY = False
CSRF_HEADER_NAME = 'HTTP_X_CSRFTOKEN'
CSRF_TRUSTED_ORIGINS = []

############
# MESSAGES #
+9 −4
Original line number Diff line number Diff line
@@ -19,7 +19,7 @@ from django.utils.http import same_origin
logger = logging.getLogger('django.request')

REASON_NO_REFERER = "Referer checking failed - no Referer."
REASON_BAD_REFERER = "Referer checking failed - %s does not match %s."
REASON_BAD_REFERER = "Referer checking failed - %s does not match any trusted origins."
REASON_NO_CSRF_COOKIE = "CSRF cookie not set."
REASON_BAD_TOKEN = "CSRF token missing or incorrect."

@@ -154,10 +154,15 @@ class CsrfViewMiddleware(object):
                if referer is None:
                    return self._reject(request, REASON_NO_REFERER)

                # Here we generate a list of all acceptable HTTP referers,
                # including the current host since that has been validated
                # upstream.
                good_hosts = list(settings.CSRF_TRUSTED_ORIGINS)
                # Note that request.get_host() includes the port.
                good_referer = 'https://%s/' % request.get_host()
                if not same_origin(referer, good_referer):
                    reason = REASON_BAD_REFERER % (referer, good_referer)
                good_hosts.append(request.get_host())
                good_referers = ['https://{0}/'.format(host) for host in good_hosts]
                if not any(same_origin(referer, host) for host in good_referers):
                    reason = REASON_BAD_REFERER % referer
                    return self._reject(request, reason)

            if csrf_token is None:
+3 −1
Original line number Diff line number Diff line
@@ -257,7 +257,8 @@ The CSRF protection is based on the following things:
   due to the fact that HTTP 'Set-Cookie' headers are (unfortunately) accepted
   by clients that are talking to a site under HTTPS.  (Referer checking is not
   done for HTTP requests because the presence of the Referer header is not
   reliable enough under HTTP.)
   reliable enough under HTTP.) Expanding the accepted referers beyond the
   current host can be done with the :setting:`CSRF_TRUSTED_ORIGINS` setting.

This ensures that only forms that have originated from your Web site can be used
to POST data back.
@@ -460,3 +461,4 @@ A number of settings can be used to control Django's CSRF behavior:
* :setting:`CSRF_COOKIE_SECURE`
* :setting:`CSRF_FAILURE_VIEW`
* :setting:`CSRF_HEADER_NAME`
* :setting:`CSRF_TRUSTED_ORIGINS`
+18 −0
Original line number Diff line number Diff line
@@ -428,6 +428,23 @@ any hyphens with underscores, and adding an ``'HTTP_'`` prefix to the name.
For example, if your client sends a ``'X-XSRF-TOKEN'`` header, the setting
should be ``'HTTP_X_XSRF_TOKEN'``.

.. setting:: CSRF_TRUSTED_ORIGINS

CSRF_TRUSTED_ORIGINS
--------------------

.. versionadded:: 1.9

Default: ``[]`` (Empty list)

A list of hosts which are trusted origins for unsafe requests (e.g. ``POST``).
For a :meth:`secure <django.http.HttpRequest.is_secure>` unsafe
request, Django's CSRF protection requires that the request have a ``Referer``
header that matches the origin present in the ``Host`` header. This prevents,
for example, a ``POST`` request from ``subdomain.example.com`` from succeeding
against ``api.example.com``. If you need cross-origin unsafe requests over
HTTPS, continuing the example, add ``"subdomain.example.com"`` to this list.

.. setting:: DATABASES

DATABASES
@@ -3374,6 +3391,7 @@ Security
  * :setting:`CSRF_COOKIE_SECURE`
  * :setting:`CSRF_FAILURE_VIEW`
  * :setting:`CSRF_HEADER_NAME`
  * :setting:`CSRF_TRUSTED_ORIGINS`

* :setting:`SECRET_KEY`
* :setting:`X_FRAME_OPTIONS`
+3 −0
Original line number Diff line number Diff line
@@ -484,6 +484,9 @@ CSRF
* The request header's name used for CSRF authentication can be customized
  with :setting:`CSRF_HEADER_NAME`.

* The new :setting:`CSRF_TRUSTED_ORIGINS` setting provides a way to allow
  cross-origin unsafe requests (e.g. ``POST``) over HTTPS.

Signals
^^^^^^^

Loading