Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

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
  • Loading branch information...
commit f913fab6be3bb4af48092d29c02e9bd5377261d4 1 parent 1ca9ced
Russell Keith-Magee authored February 10, 2011
78  docs/releases/1.1.4.txt
... ...
@@ -0,0 +1,78 @@
  1
+==========================
  2
+Django 1.1.4 release notes
  3
+==========================
  4
+
  5
+Welcome to Django 1.1.4!
  6
+
  7
+This is the fourth "bugfix" release in the Django 1.1 series,
  8
+improving the stability and performance of the Django 1.1 codebase.
  9
+
  10
+With one exception, Django 1.1.4 maintains backwards compatibility
  11
+with Django 1.1.3, but contain a number of fixes and other
  12
+improvements. Django 1.1.4 is a recommended upgrade for any
  13
+development or deployment currently using or targeting Django 1.1.
  14
+
  15
+For full details on the new features, backwards incompatibilities, and
  16
+deprecated features in the 1.1 branch, see the :doc:`/releases/1.1`.
  17
+
  18
+Backwards-incompatible changes in 1.1.4
  19
+=======================================
  20
+
  21
+CSRF exception for AJAX requests
  22
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  23
+
  24
+Django includes a CSRF-protection mechanism, which makes use of a
  25
+token inserted into outgoing forms. Middleware then checks for the
  26
+token's presence on form submission, and validates it.
  27
+
  28
+Prior to Django 1.2.5, our CSRF protection made an exception for AJAX
  29
+requests, on the following basis:
  30
+
  31
+    * Many AJAX toolkits add an X-Requested-With header when using
  32
+      XMLHttpRequest.
  33
+
  34
+    * Browsers have strict same-origin policies regarding
  35
+      XMLHttpRequest.
  36
+
  37
+    * In the context of a browser, the only way that a custom header
  38
+      of this nature can be added is with XMLHttpRequest.
  39
+
  40
+Therefore, for ease of use, we did not apply CSRF checks to requests
  41
+that appeared to be AJAX on the basis of the X-Requested-With header.
  42
+The Ruby on Rails web framework had a similar exemption.
  43
+
  44
+Recently, engineers at Google made members of the Ruby on Rails
  45
+development team aware of a combination of browser plugins and
  46
+redirects which can allow an attacker to provide custom HTTP headers
  47
+on a request to any website. This can allow a forged request to appear
  48
+to be an AJAX request, thereby defeating CSRF protection which trusts
  49
+the same-origin nature of AJAX requests.
  50
+
  51
+Michael Koziarski of the Rails team brought this to our attention, and
  52
+we were able to produce a proof-of-concept demonstrating the same
  53
+vulnerability in Django's CSRF handling.
  54
+
  55
+To remedy this, Django will now apply full CSRF validation to all
  56
+requests, regardless of apparent AJAX origin. This is technically
  57
+backwards-incompatible, but the security risks have been judged to
  58
+outweigh the compatibility concerns in this case.
  59
+
  60
+Additionally, Django will now accept the CSRF token in the custom HTTP
  61
+header X-CSRFTOKEN, as well as in the form submission itself, for ease
  62
+of use with popular JavaScript toolkits which allow insertion of
  63
+custom headers into all AJAX requests.
  64
+
  65
+The following example using the jQuery JavaScript toolkit demonstrates
  66
+this; the call to jQuery's ajaxSetup will cause all AJAX requests to
  67
+send back the CSRF token in the custom X-CSRFTOKEN header::
  68
+
  69
+    $.ajaxSetup({
  70
+        beforeSend: function(xhr, settings) {
  71
+            if (!(/^http:.*/.test(settings.url) || /^https:.*/.test(settings.url))) {
  72
+                // Only send the token to relative URLs i.e. locally.
  73
+                xhr.setRequestHeader("X-CSRFToken",
  74
+                                     $("#csrfmiddlewaretoken").val());
  75
+            }
  76
+        }
  77
+    });
  78
+
28  docs/releases/1.2.5.txt
@@ -7,7 +7,7 @@ Welcome to Django 1.2.5!
7 7
 This is the fifth "bugfix" release in the Django 1.2 series,
8 8
 improving the stability and performance of the Django 1.2 codebase.
9 9
 
10  
-With three exceptions, Django 1.2.5 maintains backwards compatibility
  10
+With four exceptions, Django 1.2.5 maintains backwards compatibility
11 11
 with Django 1.2.4, but contain a number of fixes and other
12 12
 improvements. Django 1.2.5 is a recommended upgrade for any
13 13
 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
67 67
 send back the CSRF token in the custom X-CSRFTOKEN header::
68 68
 
69 69
     $.ajaxSetup({
70  
-            beforeSend: function(xhr, settings) {
71  
-                if (!(/^http:.*/.test(settings.url) || /^https:.*/.test(settings.url))) {
72  
-                    // Only send the token to relative URLs i.e. locally.
73  
-                    xhr.setRequestHeader("X-CSRFToken",
74  
-                                         $("#csrfmiddlewaretoken").val());
  70
+        beforeSend: function(xhr, settings) {
  71
+            function getCookie(name) {
  72
+                var cookieValue = null;
  73
+                if (document.cookie && document.cookie != '') {
  74
+                    var cookies = document.cookie.split(';');
  75
+                    for (var i = 0; i < cookies.length; i++) {
  76
+                        var cookie = jQuery.trim(cookies[i]);
  77
+                        // Does this cookie string begin with the name we want?
  78
+                        if (cookie.substring(0, name.length + 1) == (name + '=')) {
  79
+                            cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
  80
+                            break;
  81
+                        }
  82
+                    }
75 83
                 }
  84
+                return cookieValue;
76 85
             }
77  
-        });
  86
+            if (!(/^http:.*/.test(settings.url) || /^https:.*/.test(settings.url))) {
  87
+                // Only send the token to relative URLs i.e. locally.
  88
+                xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
  89
+            }
  90
+        }
  91
+    });
78 92
 
79 93
 
80 94
 FileField no longer deletes files
74  docs/releases/1.3.txt
@@ -261,6 +261,80 @@ requests. These include:
261 261
 Backwards-incompatible changes in 1.3
262 262
 =====================================
263 263
 
  264
+CSRF exception for AJAX requests
  265
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  266
+
  267
+Django includes a CSRF-protection mechanism, which makes use of a
  268
+token inserted into outgoing forms. Middleware then checks for the
  269
+token's presence on form submission, and validates it.
  270
+
  271
+Prior to Django 1.2.5, our CSRF protection made an exception for AJAX
  272
+requests, on the following basis:
  273
+
  274
+    * Many AJAX toolkits add an X-Requested-With header when using
  275
+      XMLHttpRequest.
  276
+
  277
+    * Browsers have strict same-origin policies regarding
  278
+      XMLHttpRequest.
  279
+
  280
+    * In the context of a browser, the only way that a custom header
  281
+      of this nature can be added is with XMLHttpRequest.
  282
+
  283
+Therefore, for ease of use, we did not apply CSRF checks to requests
  284
+that appeared to be AJAX on the basis of the X-Requested-With header.
  285
+The Ruby on Rails web framework had a similar exemption.
  286
+
  287
+Recently, engineers at Google made members of the Ruby on Rails
  288
+development team aware of a combination of browser plugins and
  289
+redirects which can allow an attacker to provide custom HTTP headers
  290
+on a request to any website. This can allow a forged request to appear
  291
+to be an AJAX request, thereby defeating CSRF protection which trusts
  292
+the same-origin nature of AJAX requests.
  293
+
  294
+Michael Koziarski of the Rails team brought this to our attention, and
  295
+we were able to produce a proof-of-concept demonstrating the same
  296
+vulnerability in Django's CSRF handling.
  297
+
  298
+To remedy this, Django will now apply full CSRF validation to all
  299
+requests, regardless of apparent AJAX origin. This is technically
  300
+backwards-incompatible, but the security risks have been judged to
  301
+outweigh the compatibility concerns in this case.
  302
+
  303
+Additionally, Django will now accept the CSRF token in the custom HTTP
  304
+header X-CSRFTOKEN, as well as in the form submission itself, for ease
  305
+of use with popular JavaScript toolkits which allow insertion of
  306
+custom headers into all AJAX requests.
  307
+
  308
+The following example using the jQuery JavaScript toolkit demonstrates
  309
+this; the call to jQuery's ajaxSetup will cause all AJAX requests to
  310
+send back the CSRF token in the custom X-CSRFTOKEN header::
  311
+
  312
+    $.ajaxSetup({
  313
+        beforeSend: function(xhr, settings) {
  314
+            function getCookie(name) {
  315
+                var cookieValue = null;
  316
+                if (document.cookie && document.cookie != '') {
  317
+                    var cookies = document.cookie.split(';');
  318
+                    for (var i = 0; i < cookies.length; i++) {
  319
+                        var cookie = jQuery.trim(cookies[i]);
  320
+                        // Does this cookie string begin with the name we want?
  321
+                        if (cookie.substring(0, name.length + 1) == (name + '=')) {
  322
+                            cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
  323
+                            break;
  324
+                        }
  325
+                    }
  326
+                }
  327
+                return cookieValue;
  328
+            }
  329
+            if (!(/^http:.*/.test(settings.url) || /^https:.*/.test(settings.url))) {
  330
+                // Only send the token to relative URLs i.e. locally.
  331
+                xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
  332
+            }
  333
+        }
  334
+    });
  335
+
  336
+
  337
+
264 338
 FileField no longer deletes files
265 339
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
266 340
 
1  docs/releases/index.txt
@@ -36,6 +36,7 @@ Final releases
36 36
 .. toctree::
37 37
    :maxdepth: 1
38 38
 
  39
+   1.1.4
39 40
    1.1.2
40 41
    1.1
41 42
 

0 notes on commit f913fab

Please sign in to comment.
Something went wrong with that request. Please try again.