VYPR
High severityNVD Advisory· Published Feb 14, 2011· Updated Apr 29, 2026

CVE-2011-0696

CVE-2011-0696

Description

Django 1.1.x before 1.1.4 and 1.2.x before 1.2.5 does not properly validate HTTP requests that contain an X-Requested-With header, which makes it easier for remote attackers to conduct cross-site request forgery (CSRF) attacks via forged AJAX requests that leverage a "combination of browser plugins and redirects," a related issue to CVE-2011-0447.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
DjangoPyPI
>= 1.1, < 1.1.41.1.4
DjangoPyPI
>= 1.2, < 1.2.51.2.5

Affected products

9
  • cpe:2.3:a:djangoproject:django:1.1:*:*:*:*:*:*:*+ 8 more
    • cpe:2.3:a:djangoproject:django:1.1:*:*:*:*:*:*:*
    • cpe:2.3:a:djangoproject:django:1.1.0:*:*:*:*:*:*:*
    • cpe:2.3:a:djangoproject:django:1.1.2:*:*:*:*:*:*:*
    • cpe:2.3:a:djangoproject:django:1.1.3:*:*:*:*:*:*:*
    • cpe:2.3:a:djangoproject:django:1.2:*:*:*:*:*:*:*
    • cpe:2.3:a:djangoproject:django:1.2.1:*:*:*:*:*:*:*
    • cpe:2.3:a:djangoproject:django:1.2.2:*:*:*:*:*:*:*
    • cpe:2.3:a:djangoproject:django:1.2.3:*:*:*:*:*:*:*
    • cpe:2.3:a:djangoproject:django:1.2.4:*:*:*:*:*:*:*

Patches

2
408c5c873ce1

[1.1.X] Fixed a security issue in the CSRF component. Disclosure and new release forthcoming.

https://github.com/django/djangoAlex GaynorFeb 9, 2011via ghsa
3 files changed · +37 21
  • django/contrib/csrf/middleware.py+6 6 modified
    @@ -37,9 +37,6 @@ def process_view(self, request, callback, callback_args, callback_kwargs):
                 if getattr(callback, 'csrf_exempt', False):
                     return None
     
    -            if request.is_ajax():
    -                return None
    -
                 try:
                     session_id = request.COOKIES[settings.SESSION_COOKIE_NAME]
                 except KeyError:
    @@ -48,9 +45,12 @@ def process_view(self, request, callback, callback_args, callback_kwargs):
     
                 csrf_token = _make_token(session_id)
                 # check incoming token
    -            try:
    -                request_csrf_token = request.POST['csrfmiddlewaretoken']
    -            except KeyError:
    +            request_csrf_token = request.POST.get('csrfmiddlewaretoken', '')
    +            if request_csrf_token == "":
    +                # Fall back to X-CSRFToken, to make things easier for AJAX
    +                request_csrf_token = request.META.get('HTTP_X_CSRFTOKEN', '')
    +
    +            if request_csrf_token == "":
                     return HttpResponseForbidden(_ERROR_MSG)
     
                 if request_csrf_token != csrf_token:
    
  • django/contrib/csrf/tests.py+3 3 modified
    @@ -135,12 +135,12 @@ def test_process_request_session_no_token_exempt_view(self):
             req2 = CsrfMiddleware().process_view(req, csrf_exempt(self.get_view()), (), {})
             self.assertEquals(None, req2)
     
    -    def test_ajax_exemption(self):
    +    def test_csrf_token_in_header(self):
             """
    -        Check that AJAX requests are automatically exempted.
    +        Check that we can pass in the token in a header instead of in the form
             """
             req = self._get_POST_session_request()
    -        req.META['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest'
    +        req.META['HTTP_X_CSRFTOKEN'] = _make_token(self._session_id)
             req2 = CsrfMiddleware().process_view(req, self.get_view(), (), {})
             self.assertEquals(None, req2)
     
    
  • docs/ref/contrib/csrf.txt+28 12 modified
    @@ -39,6 +39,34 @@ replaced instead of using ``CsrfMiddleware``.
         (previous versions of Django did not provide these two components
         of ``CsrfMiddleware`` as described above)
     
    +AJAX
    +----
    +
    +While the above method can be used with AJAX POST requests, it has some
    +inconveniences: you have to remember to get the CSRF token from the HTML
    +document and pass it in as POST data with every POST request. For this reason,
    +there is an alternative method: on each XMLHttpRequest, set a custom
    +`X-CSRFToken` header to the value of the CSRF token. This is often easier,
    +because many javascript frameworks provide hooks that allow headers to be set on
    +every request. In jQuery, you can use the ``beforeSend`` hook as follows:
    +
    +.. code-block:: javascript
    +
    +    $.ajaxSetup({
    +        beforeSend: function(xhr, settings) {
    +            if (!(/^http:.*/.test(settings.url) || /^https:.*/.test(settings.url))) {
    +                // Only send the token to relative URLs i.e. locally.
    +                xhr.setRequestHeader("X-CSRFToken",
    +                                     $("#csrfmiddlewaretoken").val());
    +            }
    +        }
    +    });
    +
    +Adding this to a javascript file that is included on your site will ensure that
    +AJAX POST requests that are made via jQuery will not be caught by the CSRF
    +protection. This will only work if you remember to include a form on the page,
    +so that the input with id 'csrfmiddlewaretoken' will be found.
    +
     Exceptions
     ----------
     
    @@ -61,10 +89,6 @@ disable the view protection mechanism (``CsrfViewMiddleware``) and the
     response post-processing (``CsrfResponseMiddleware``) respectively.
     They can be used individually if required.
     
    -You don't have to worry about doing this for most AJAX views. Any
    -request sent with "X-Requested-With: XMLHttpRequest" is automatically
    -exempt. (See the next section.)
    -
     How it works
     ============
     
    @@ -98,14 +122,6 @@ The Content-Type is checked before modifying the response, and only
     pages that are served as 'text/html' or 'application/xml+xhtml'
     are modified.
     
    -The middleware tries to be smart about requests that come in via AJAX. Many
    -JavaScript toolkits send an "X-Requested-With: XMLHttpRequest" HTTP header;
    -these requests are detected and automatically *not* handled by this middleware.
    -We can do this safely because, in the context of a browser, the header can only
    -be added by using ``XMLHttpRequest``, and browsers already implement a
    -same-domain policy for ``XMLHttpRequest``. (Note that this is not secure if you
    -don't trust content within the same domain or subdomains.)
    -
     
     .. _9.1.1 Safe Methods, HTTP 1.1, RFC 2616: http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html
     
    
818e70344e71

[1.2.X] Fixed a security issue in the CSRF componenent. Disclosure and new release forthcoming.

https://github.com/django/djangoAlex GaynorFeb 9, 2011via ghsa
3 files changed · +50 51
  • django/middleware/csrf.py+6 26 modified
    @@ -97,6 +97,7 @@ def _reject(self, request, reason):
             return _get_failure_view()(request, reason=reason)
     
         def process_view(self, request, callback, callback_args, callback_kwargs):
    +
             if getattr(request, 'csrf_processing_done', False):
                 return None
     
    @@ -130,31 +131,6 @@ def process_view(self, request, callback, callback_args, callback_kwargs):
                     # any branches that call reject()
                     return self._accept(request)
     
    -            if request.is_ajax():
    -                # .is_ajax() is based on the presence of X-Requested-With.  In
    -                # the context of a browser, this can only be sent if using
    -                # XmlHttpRequest.  Browsers implement careful policies for
    -                # XmlHttpRequest:
    -                #
    -                #  * Normally, only same-domain requests are allowed.
    -                #
    -                #  * Some browsers (e.g. Firefox 3.5 and later) relax this
    -                #    carefully:
    -                #
    -                #    * if it is a 'simple' GET or POST request (which can
    -                #      include no custom headers), it is allowed to be cross
    -                #      domain.  These requests will not be recognized as AJAX.
    -                #
    -                #    * if a 'preflight' check with the server confirms that the
    -                #      server is expecting and allows the request, cross domain
    -                #      requests even with custom headers are allowed. These
    -                #      requests will be recognized as AJAX, but can only get
    -                #      through when the developer has specifically opted in to
    -                #      allowing the cross-domain POST request.
    -                #
    -                # So in all cases, it is safe to allow these requests through.
    -                return self._accept(request)
    -
                 if request.is_secure():
                     # Strict referer checking for HTTPS
                     referer = request.META.get('HTTP_REFERER')
    @@ -185,7 +161,11 @@ def process_view(self, request, callback, callback_args, callback_kwargs):
                     csrf_token = request.META["CSRF_COOKIE"]
     
                 # check incoming token
    -            request_csrf_token = request.POST.get('csrfmiddlewaretoken', None)
    +            request_csrf_token = request.POST.get('csrfmiddlewaretoken', "")
    +            if request_csrf_token == "":
    +                # Fall back to X-CSRFToken, to make things easier for AJAX
    +                request_csrf_token = request.META.get('HTTP_X_CSRFTOKEN', '')
    +
                 if request_csrf_token != csrf_token:
                     if cookie_is_new:
                         # probably a problem setting the CSRF cookie
    
  • docs/ref/contrib/csrf.txt+41 22 modified
    @@ -81,6 +81,47 @@ The utility script ``extras/csrf_migration_helper.py`` can help to automate the
     finding of code and templates that may need to be upgraded.  It contains full
     help on how to use it.
     
    +AJAX
    +----
    +
    +While the above method can be used for AJAX POST requests, it has some
    +inconveniences: you have to remember to pass the CSRF token in as POST data with
    +every POST request. For this reason, there is an alternative method: on each
    +XMLHttpRequest, set a custom `X-CSRFToken` header to the value of the CSRF
    +token. This is often easier, because many javascript frameworks provide hooks
    +that allow headers to be set on every request. In jQuery, you can use the
    +``beforeSend`` hook as follows:
    +
    +.. code-block:: javascript
    +
    +    $.ajaxSetup({
    +        beforeSend: function(xhr, settings) {
    +            function getCookie(name) {
    +                var cookieValue = null;
    +                if (document.cookie && document.cookie != '') {
    +                    var cookies = document.cookie.split(';');
    +                    for (var i = 0; i < cookies.length; i++) {
    +                        var cookie = jQuery.trim(cookies[i]);
    +                        // Does this cookie string begin with the name we want?
    +                        if (cookie.substring(0, name.length + 1) == (name + '=')) {
    +                            cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
    +                            break;
    +                        }
    +                    }
    +                }
    +                return cookieValue;
    +            }
    +            if (!(/^http:.*/.test(settings.url) || /^https:.*/.test(settings.url))) {
    +                // Only send the token to relative URLs i.e. locally.
    +                xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
    +            }
    +        }
    +    });
    +
    +Adding this to a javascript file that is included on your site will ensure that
    +AJAX POST requests that are made via jQuery will not be caught by the CSRF
    +protection.
    +
     The decorator method
     --------------------
     
    @@ -262,10 +303,6 @@ in the same module.  These disable the view protection mechanism
     (``CsrfResponseMiddleware``) respectively.  They can be used individually if
     required.
     
    -You don't have to worry about doing this for most AJAX views. Any request sent
    -with "X-Requested-With: XMLHttpRequest" is automatically exempt. (See the `How
    -it works`_ section.)
    -
     Subdomains
     ----------
     
    @@ -343,24 +380,6 @@ request ought to be harmless.
     response, and only pages that are served as 'text/html' or
     'application/xml+xhtml' are modified.
     
    -AJAX
    -----
    -
    -The middleware tries to be smart about requests that come in via AJAX. Most
    -modern JavaScript toolkits send an "X-Requested-With: XMLHttpRequest" HTTP
    -header; these requests are detected and automatically *not* handled by this
    -middleware.  We can do this safely because, in the context of a browser, the
    -header can only be added by using ``XMLHttpRequest``, and browsers already
    -implement a same-domain policy for ``XMLHttpRequest``.
    -
    -For the more recent browsers that relax this same-domain policy, custom headers
    -like "X-Requested-With" are only allowed after the browser has done a
    -'preflight' check to the server to see if the cross-domain request is allowed,
    -using a strictly 'opt in' mechanism, so the exception for AJAX is still safe—if
    -the developer has specifically opted in to allowing cross-site AJAX POST
    -requests on a specific URL, they obviously don't want the middleware to disallow
    -exactly that.
    -
     .. _9.1.1 Safe Methods, HTTP 1.1, RFC 2616: http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html
     
     Caching
    
  • tests/regressiontests/csrf_tests/tests.py+3 3 modified
    @@ -275,12 +275,12 @@ def test_process_request_csrf_cookie_no_token_exempt_view(self):
             req2 = CsrfMiddleware().process_view(req, csrf_exempt(post_form_view), (), {})
             self.assertEquals(None, req2)
     
    -    def test_ajax_exemption(self):
    +    def test_csrf_token_in_header(self):
             """
    -        Check that AJAX requests are automatically exempted.
    +        Check that we can pass in the token in a header instead of in the form
             """
             req = self._get_POST_csrf_cookie_request()
    -        req.META['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest'
    +        req.META['HTTP_X_CSRFTOKEN'] = self._csrf_id
             req2 = CsrfMiddleware().process_view(req, post_form_view, (), {})
             self.assertEquals(None, req2)
     
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

24

News mentions

0

No linked articles in our index yet.