Django includes a CSRF-protection mechanism, which makes use of a token
inserted into outgoing forms. Middleware then checks for the token's
presence on form submission, and validates it.
Previously, however, our CSRF protection made an exception for AJAX
requests, on the following basis:
1. Many AJAX toolkits add an X-Requested-With header when using
2. Browsers have strict same-origin policies regarding XMLHttpRequest.
3. In the context of a browser, the only way that a custom header of
this nature can be added is with XMLHttpRequest.
Therefore, for ease of use, we did not apply CSRF checks to requests that
appeared to be AJAX on the basis of the X-Requested-With header. The Ruby
on Rails web framework had a similar exemption.
Recently, engineers at Google made members of the Ruby on Rails development
team aware of a combination of browser plugins and redirects which can
allow an attacker to provide custom HTTP headers on a request to any
website. This can allow a forged request to appear to be an AJAX request,
thereby defeating CSRF protection which trusts the same-origin nature of
Michael Koziarski of the Rails team brought this to our attention, and we
were able to produce a proof-of-concept demonstrating the same
vulnerability in Django's CSRF handling.
To remedy this, Django will now apply full CSRF validation to all requests,
regardless of apparent AJAX origin. This is technically
backwards-incompatible, but the security risks have been judged to outweigh
the compatibility concerns in this case.
Additionally, Django will now accept the CSRF token in the custom HTTP
header X-CSRFTOKEN, as well as in the form submission itself, for ease of
headers into all AJAX requests.
Created Django tracking bugs for this issue
Affects: fedora-all [bug 676360]
*** Bug 676459 has been marked as a duplicate of this bug. ***
All our branches now have either 1.2.5 or 1.1.4 as stable releases -- it appears that they were pushed without tagging the affected bugs.