Ticket #25334: 24496.diff

File 24496.diff, 6.0 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..676026a 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 trusted origins."
    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..ba24339 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
     261   current host can be done with the :setting:`CSRF_TRUSTED_ORIGINS` setting.
    261262
    262263This ensures that only forms that have originated from your Web site can be used
    263264to POST data back.
    A number of settings can be used to control Django's CSRF behavior:  
    460461* :setting:`CSRF_COOKIE_SECURE`
    461462* :setting:`CSRF_FAILURE_VIEW`
    462463* :setting:`CSRF_HEADER_NAME`
     464* :setting:`CSRF_TRUSTED_ORIGINS`
  • docs/ref/settings.txt

    diff --git a/docs/ref/settings.txt b/docs/ref/settings.txt
    index 217f542..ee879c5 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
     431.. setting:: CSRF_TRUSTED_ORIGINS
     432
     433CSRF_TRUSTED_ORIGINS
     434--------------------
     435
     436.. versionadded:: 1.9
     437
     438Default: ``[]`` (Empty list)
     439
     440A list of hosts which are trusted origins for unsafe (e.g. ``POST``) requests.
     441For secure (i.e. where ``request.is_secure()`` returns ``True``) unsafe
     442request, Django's CSRF protection requires that the request have a ``Referer``
     443header that matches the origin present in the ``Host`` header. This prevents,
     444for example, a ``POST`` request from ``subdomain.example.com`` from succeeding
     445against ``api.example.com``. If you need cross-origin unsafe requests over
     446HTTPS, continuing the example, add ``"subdomain.example.com"`` to this list.
     447
    431448.. setting:: DATABASES
    432449
    433450DATABASES
    Security  
    33743391  * :setting:`CSRF_COOKIE_SECURE`
    33753392  * :setting:`CSRF_FAILURE_VIEW`
    33763393  * :setting:`CSRF_HEADER_NAME`
     3394  * :setting:`CSRF_TRUSTED_ORIGINS`
    33773395
    33783396* :setting:`SECRET_KEY`
    33793397* :setting:`X_FRAME_OPTIONS`
  • docs/releases/1.9.txt

    diff --git a/docs/releases/1.9.txt b/docs/releases/1.9.txt
    index 85420bc..422b8c3 100644
    a b CSRF  
    484484* The request header's name used for CSRF authentication can be customized
    485485  with :setting:`CSRF_HEADER_NAME`.
    486486
     487* The setting :setting:`CSRF_TRUSTED_ORIGINS` was added to allow cross origin
     488  unsafe (e.g. ``POST``) requests under HTTPS.
     489
    487490Signals
    488491^^^^^^^
    489492
  • docs/spelling_wordlist

    diff --git a/docs/spelling_wordlist b/docs/spelling_wordlist
    index 691ab2f..1edaa68 100644
    a b refactoring  
    644644refactorings
    645645refactors
    646646referer
     647referers
    647648reflow
    648649regex
    649650regexes
  • tests/csrf_tests/tests.py

    diff --git a/tests/csrf_tests/tests.py b/tests/csrf_tests/tests.py
    index 2d347cc..aaa9a69 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        A POST HTTPS request with a referer added to the CSRF_TRUSTED_ORIGINS
     359        setting is accepted.
     360        """
     361        req = self._get_POST_request_with_token()
     362        req._is_secure_override = True
     363        req.META['HTTP_HOST'] = 'www.example.com'
     364        req.META['HTTP_REFERER'] = 'https://dashboard.example.com'
     365        req2 = CsrfViewMiddleware().process_view(req, post_form_view, (), {})
     366        self.assertIsNone(req2)
     367
    355368    def test_ensures_csrf_cookie_no_middleware(self):
    356369        """
    357370        Tests that ensures_csrf_cookie decorator fulfils its promise
Back to Top