Security releases issued

Posted by James Bennett on February 8, 2011

Today the Django team is issuing multiple releases -- Django 1.2.5 and Django 1.1.4 -- to remedy three security issues reported to us. All users of affected versions of Django are urged to upgrade immediately.

Flaw in CSRF handling

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 XMLHttpRequest.
  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 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());
            }
        }
    });

For reference, the Ruby on Rails team's announcement regarding this issue may be viewed here.

Potential XSS in file field rendering

Django's form system includes form fields and widgets for performing file uploads; in rendering these fields, the name of the file currently stored in the field is displayed. In the process of rendering, the filename is displayed without being escaped, as reported by Trac user "e.generalov".

In many cases this does not result in a cross-site-scripting vulnerability, as file-storage backends can and are encouraged to (and the default backends provided with Django do) sanitize the supplied filename according to their requirements. However, the risk of a vulnerability appearing in a backend which does not sanitize, or which performs insufficient sanitization, is such that Django will now automatically escape filenames in form rendering.

Directory-traversal vulnerability on Windows

Django's file-based session-storage backend stores session data in a file named with the session key. This backend validates that the key submitted in the session cookie does not contain the filesystem path separator character, as specified by Python's os.path.sep, and if that character is found in the key an exception is raised.

As mentioned in a report to the Django team by Paul McMillan, however, this is insufficient on Windows, as filesystem operations on Windows accept multiple potential path separators (os.path.sep for Windows is the backslash character; the forward slash character is also accepted). Due to other verification mechanisms -- sessions are also stored with a hash of their contents, and the hash is verified on session deserialization -- this does not automatically allow arbitrary loading or execution of files. However, due to the possibility of session replays, or more serious vulnerabilities if an attacker manages to defeat the session verification, the file-based session backend will now use an explicit whitelist of characters which may appear in session keys. This whitelist excludes all valid path separators.

Affected versions

All three of the issues described above are present in the following currently-supported Django versions:

Resolution

Patches have been applied to Django trunk, and to the 1.2 and 1.1 release branches, which resolve the issues described above. The patches may be obtained directly from the following changesets:

The following new releases have been issued:

As Django trunk is currently in a beta state, users are strongly advised not to be running production deployments from it; if you are currently doing so, however, you are urged to upgrade immediately to the latest trunk, which contains patches for these issues.

General notes regarding security

As always, we ask that potential security issues be reported via private email to security@djangoproject.com, and not via Django's Trac instance or the django-developers list.

If you are or represent a third-party distributor of Django and did not receive a notification email regarding this announcement from the Django release manager, please contact james@b-list.org.

Back to Top