Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Date: Mon, 30 Jul 2012 19:16:47 -0600
From: Kurt Seifried <>
To: "" <>
Subject: CVE Request: Django 1.3.1 and 1.4.0 security issues

Hash: SHA1

Security releases issued

Today the Django team is issuing multiple releases -- Django 1.3.2 and
Django 1.4.1 -- to remedy security issues reported to us.

All users are encouraged to upgrade Django immediately.

Cross-site scripting in authentication views

The login() and logout() views provided in Django's authentication
framework make use of the common "POST-redirect-GET" pattern; a
configurable querystring parameter can be used to specify the location
to redirect to on successful submission. Currently, those views
perform basic validation to ensure that the redirect location does not
specify a different domain.

However, this validation does not check the scheme of the target URL;
armed with this knowledge, an attacker can craft, for example, a data:
scheme URL which will execute JavaScript.

Some browsers are known to currently provide protection against this
issue: Google Chrome in particular explicitly disallows redirects to
data: scheme URLs. However, several other major browsers do permit
such redirects.

After careful consideration of this issue, we have decided that the
safest course of action involves a slight break to backwards
compatibility. Although temporary mitigation could be achieved through
more stringent validation in the relevant views, the root issue lies
in Django's HTTP response classes, which currently do not perform any
validation of redirect targets. The fact that some major browsers
already disallow certain URL schemes in redirects indicates that the
impact of this change is likely to be minimal.

As such, the following change is being made despite breaking API

    django.http.HttpResponseRedirect and
django.http.HttpResponsePermanentRedirect now subclass a common base
class, django.http.HttpResponseRedirectBase.
    That base class defines an explicit whitelist of allowed URL
schemes. Attempts to instantiate a redirect with a URL of a scheme not
in the whitelist will raise the exception
django.core.exceptions.SuspiciousOperation, which is already employed
for similar purposes in other parts of Django's codebase (e.g., to
warn of possible session tampering).

End-user code which issues redirects is unlikely to be affected unless
it either explicitly requires redirecting to an unsupported scheme, or
accepts the target URL from a user-supplied parameter.

In the former case, subclassing the appropriate redirect class
(HttpResponseRedirect for status code 302,
HttpResponsePermanentRedirect for status code 301) and overriding the
allowed_schemes list will be sufficient. The default value of
allowed_schemes is ['http', 'https', 'ftp'].

In the latter case, code which accepts user-supplied parameters can
attempt to instantiate the redirect, catch the SuspiciousOperation
exception, and fall back to an alternate location as needed.

At present, Django's authentication views will leave this exception
uncaught. This means site administrators will receive error reports
if/when that exception is raised. It is likely that future Django
releases will begin catching this exception, after allowing some time
for users of Django to observe behavior and judge their exposure to
potential issues.

Denial-of-service in image validation

Django's form system includes field types for handling file uploads,
including a field class -- django.forms.ImageField -- for uploading
images, which can perform some validation of image formats.

Part of that validation involves detecting corrupted image files,
using routines provided by the Python Imaging Library (PIL).

The check as it currently exists in Django is vulnerable, however,
because it will read the entire image file, including decompressing
compressed formats as needed. It is trivially possible to craft a
reasonably-sized file which, when decompressed in this fashion, grows
to enormous size, consuming available memory and offering the ability
to perform a denial-of-service attack.

To mitigate this, image validation will now make use of PIL's
Image.verify() method, which performs some validation checks but does
not decompress or read the entire image file.

Denial-of-service via get_image_dimensions()

Django's image-handling facilities also include helper methods to
determine the dimensions of an image. Currently, the process for this
involves reading a 1024-byte chunk from the start of the file, and
passing to PIL to determine the dimensions; if insufficient data is
provided, further 1024-byte chunks are read until PIL is able to
return a definite answer.

While this works well for image formats which store enough information
in their headers to determine dimensions, it can result in large
quantities of read/process cycles for formats which do not. In
particular, larger TIFF images can require tens of thousands of such
cycles, tying up or timing out worker processes/threads and consuming
enough server resources to result in an effective denial-of-service.

To mitigate this, the algorithm for determining image dimensions is
being changed; the initial attempt will still use a 1024-byte chunk,
but the chunk size will be doubled on each successive read. Testing
has demonstrated that this reduces time to process TIFF files by
multiple orders of magnitude.

- -- 
Kurt Seifried Red Hat Security Response Team (SRT)
PGP: 0x5E267993 A90B F995 7350 148F 66BF 7554 160D 4553 5E26 7993

Version: GnuPG v1.4.12 (GNU/Linux)
Comment: Using GnuPG with Mozilla -


Powered by blists - more mailing lists

Please check out the Open Source Software Security Wiki, which is counterpart to this mailing list.

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.