Commits

Anonymous committed 0f218d1

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

Comments (0)

Files changed (3)

django/contrib/csrf/middleware.py

             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:
 
             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

         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

     (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
 ----------
 
 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
 ============
 
 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
 
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.