From f913fab6be3bb4af48092d29c02e9bd5377261d4 Mon Sep 17 00:00:00 2001 From: Russell Keith-Magee Date: Thu, 10 Feb 2011 09:27:38 +0000 Subject: [PATCH] Fixed #15253, #15259 -- Added 1.1.4 release notes, added a section on CSRF changes to the 1.3 release notes, and corrected the example in the 1.2.5 release notes. Thanks to Gary Wilson and Mark Hellewell for the reports. git-svn-id: http://code.djangoproject.com/svn/django/trunk@15482 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- docs/releases/1.1.4.txt | 78 +++++++++++++++++++++++++++++++++++++++++ docs/releases/1.2.5.txt | 28 +++++++++++---- docs/releases/1.3.txt | 74 ++++++++++++++++++++++++++++++++++++++ docs/releases/index.txt | 1 + 4 files changed, 174 insertions(+), 7 deletions(-) create mode 100644 docs/releases/1.1.4.txt diff --git a/docs/releases/1.1.4.txt b/docs/releases/1.1.4.txt new file mode 100644 index 0000000000..dbe91fb3e4 --- /dev/null +++ b/docs/releases/1.1.4.txt @@ -0,0 +1,78 @@ +========================== +Django 1.1.4 release notes +========================== + +Welcome to Django 1.1.4! + +This is the fourth "bugfix" release in the Django 1.1 series, +improving the stability and performance of the Django 1.1 codebase. + +With one exception, Django 1.1.4 maintains backwards compatibility +with Django 1.1.3, but contain a number of fixes and other +improvements. Django 1.1.4 is a recommended upgrade for any +development or deployment currently using or targeting Django 1.1. + +For full details on the new features, backwards incompatibilities, and +deprecated features in the 1.1 branch, see the :doc:`/releases/1.1`. + +Backwards-incompatible changes in 1.1.4 +======================================= + +CSRF exception for AJAX requests +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +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. + +Prior to Django 1.2.5, our CSRF protection made an exception for AJAX +requests, on the following basis: + + * Many AJAX toolkits add an X-Requested-With header when using + XMLHttpRequest. + + * Browsers have strict same-origin policies regarding + XMLHttpRequest. + + * 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 AJAX requests. + +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 use with popular JavaScript toolkits which allow insertion of +custom headers into all AJAX requests. + +The following example using the jQuery JavaScript toolkit demonstrates +this; the call to jQuery's ajaxSetup will cause all AJAX requests to +send back the CSRF token in the custom X-CSRFTOKEN header:: + + $.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()); + } + } + }); + diff --git a/docs/releases/1.2.5.txt b/docs/releases/1.2.5.txt index 7482e09a8f..68c301a945 100644 --- a/docs/releases/1.2.5.txt +++ b/docs/releases/1.2.5.txt @@ -7,7 +7,7 @@ Welcome to Django 1.2.5! This is the fifth "bugfix" release in the Django 1.2 series, improving the stability and performance of the Django 1.2 codebase. -With three exceptions, Django 1.2.5 maintains backwards compatibility +With four exceptions, Django 1.2.5 maintains backwards compatibility with Django 1.2.4, but contain a number of fixes and other improvements. Django 1.2.5 is a recommended upgrade for any development or deployment currently using or targeting Django 1.2. @@ -67,14 +67,28 @@ this; the call to jQuery's ajaxSetup will cause all AJAX requests to send back the CSRF token in the custom X-CSRFTOKEN header:: $.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()); + 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')); + } + } + }); FileField no longer deletes files diff --git a/docs/releases/1.3.txt b/docs/releases/1.3.txt index 4792eb83fa..5b33a3c88e 100644 --- a/docs/releases/1.3.txt +++ b/docs/releases/1.3.txt @@ -261,6 +261,80 @@ requests. These include: Backwards-incompatible changes in 1.3 ===================================== +CSRF exception for AJAX requests +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +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. + +Prior to Django 1.2.5, our CSRF protection made an exception for AJAX +requests, on the following basis: + + * Many AJAX toolkits add an X-Requested-With header when using + XMLHttpRequest. + + * Browsers have strict same-origin policies regarding + XMLHttpRequest. + + * 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 AJAX requests. + +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 use with popular JavaScript toolkits which allow insertion of +custom headers into all AJAX requests. + +The following example using the jQuery JavaScript toolkit demonstrates +this; the call to jQuery's ajaxSetup will cause all AJAX requests to +send back the CSRF token in the custom X-CSRFTOKEN header:: + + $.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')); + } + } + }); + + + FileField no longer deletes files ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/docs/releases/index.txt b/docs/releases/index.txt index 5897d42722..b687e44dca 100644 --- a/docs/releases/index.txt +++ b/docs/releases/index.txt @@ -36,6 +36,7 @@ Final releases .. toctree:: :maxdepth: 1 + 1.1.4 1.1.2 1.1