Ticket #24496: 24496.diff

File 24496.diff, 4.6 KB (added by Joshua Kehn, 9 years ago)
  • django/conf/global_settings.py

    diff --git a/django/conf/global_settings.py b/django/conf/global_settings.py
    index 280bfeb..6b759d8 100644
    a b CSRF_COOKIE_PATH = '/'  
    558558CSRF_COOKIE_SECURE = False
    559559CSRF_COOKIE_HTTPONLY = False
    560560CSRF_HEADER_NAME = 'HTTP_X_CSRFTOKEN'
     561CSRF_TRUSTED_ORIGINS = []
    561562
    562563############
    563564# MESSAGES #
  • django/middleware/csrf.py

    diff --git a/django/middleware/csrf.py b/django/middleware/csrf.py
    index 6d16a92..dc00a70 100644
    a b from django.utils.http import same_origin  
    1919logger = logging.getLogger('django.request')
    2020
    2121REASON_NO_REFERER = "Referer checking failed - no Referer."
    22 REASON_BAD_REFERER = "Referer checking failed - %s does not match %s."
     22REASON_BAD_REFERER = "Referer checking failed - %s does not match any allowed hosts."
    2323REASON_NO_CSRF_COOKIE = "CSRF cookie not set."
    2424REASON_BAD_TOKEN = "CSRF token missing or incorrect."
    2525
    class CsrfViewMiddleware(object):  
    154154                if referer is None:
    155155                    return self._reject(request, REASON_NO_REFERER)
    156156
     157                # Here we generate a list of all acceptable HTTP referers,
     158                # including the current host since that has been validated
     159                # upstream.
     160                #
    157161                # Note that request.get_host() includes the port.
    158                 good_referer = 'https://%s/' % request.get_host()
    159                 if not same_origin(referer, good_referer):
    160                     reason = REASON_BAD_REFERER % (referer, good_referer)
     162                good_hosts = list(settings.CSRF_TRUSTED_ORIGINS)
     163                good_hosts.append(request.get_host())
     164                good_referers = ['https://{0}/'.format(host) for host in good_hosts]
     165                if not any([same_origin(referer, host) for host in good_referers]):
     166                    reason = REASON_BAD_REFERER % (referer)
    161167                    return self._reject(request, reason)
    162168
    163169            if csrf_token is None:
  • docs/ref/csrf.txt

    diff --git a/docs/ref/csrf.txt b/docs/ref/csrf.txt
    index 5909905..7f37f8a 100644
    a b The CSRF protection is based on the following things:  
    257257   due to the fact that HTTP 'Set-Cookie' headers are (unfortunately) accepted
    258258   by clients that are talking to a site under HTTPS.  (Referer checking is not
    259259   done for HTTP requests because the presence of the Referer header is not
    260    reliable enough under HTTP.)
     260   reliable enough under HTTP.) Expanding the accepted referers beyond the current host can be done with the :setting:`CSRF_TRUSTED_ORIGINS` setting.
    261261
    262262This ensures that only forms that have originated from your Web site can be used
    263263to POST data back.
    A number of settings can be used to control Django's CSRF behavior:  
    460460* :setting:`CSRF_COOKIE_SECURE`
    461461* :setting:`CSRF_FAILURE_VIEW`
    462462* :setting:`CSRF_HEADER_NAME`
     463* :setting:`CSRF_TRUSTED_ORIGINS`
  • docs/ref/settings.txt

    diff --git a/docs/ref/settings.txt b/docs/ref/settings.txt
    index 217f542..776c422 100644
    a b any hyphens with underscores, and adding an ``'HTTP_'`` prefix to the name.  
    428428For example, if your client sends a ``'X-XSRF-TOKEN'`` header, the setting
    429429should be ``'HTTP_X_XSRF_TOKEN'``.
    430430
     431CSRF_TRUSTED_ORIGINS
     432----------------
     433
     434.. versionadded:: 1.9
     435
     436Default: ``[]``
     437
     438An iterable containing domains which will be included as part of the referer checks during CSRF processing of secure requests.
     439
    431440.. setting:: DATABASES
    432441
    433442DATABASES
  • tests/csrf_tests/tests.py

    diff --git a/tests/csrf_tests/tests.py b/tests/csrf_tests/tests.py
    index 2d347cc..41a2aed 100644
    a b class CsrfViewMiddlewareTest(SimpleTestCase):  
    352352        req2 = CsrfViewMiddleware().process_view(req, post_form_view, (), {})
    353353        self.assertIsNone(req2)
    354354
     355    @override_settings(ALLOWED_HOSTS=['www.example.com'], CSRF_TRUSTED_ORIGINS=['dashboard.example.com'])
     356    def test_https_csrf_trusted_origin_allowed(self):
     357        """
     358        Test that a POST HTTPS request with a referer added to the
     359        CSRF_TRUSTED_ORIGINS setting is accepted
     360        """
     361        # See ticket #24496
     362        req = self._get_POST_request_with_token()
     363        req._is_secure_override = True
     364        req.META['HTTP_HOST'] = 'www.example.com'
     365        req.META['HTTP_REFERER'] = 'https://dashboard.example.com'
     366        req2 = CsrfViewMiddleware().process_view(req, post_form_view, (), {})
     367        self.assertIsNone(req2)
     368
    355369    def test_ensures_csrf_cookie_no_middleware(self):
    356370        """
    357371        Tests that ensures_csrf_cookie decorator fulfils its promise
Back to Top