Today the Django team is issuing multiple releases --
Django 1.2.6 and Django 1.3.1 -- to remedy security issues
reported to us. Additionally, this announcement contains
advisories for several other issues which, while not
requiring changes to Django itself, will be of concern
to users of Django.
All users are encouraged to upgrade Django, and to implement
the recommendations in these advisories, immediately.
Session manipulation
Django's session framework, django.contrib.sessions, is
configurable to use any of multiple backends for storage of
session data. One such backend, provided with Django itself,
integrates with Django's cache framework to use the cache as
storage for session data.
When configured in this fashion using memory-based sessions
and caching, Django sessions are stored directly in the root
namespace of the cache, using session identifiers as keys.
This results in a potential attack when coupled with an
application storing user-supplied data in the cache; if an
attacker can cause data to be cached using a key which is
also a valid session identifier, Django's session framework
will treat that data -- so long as it is a dictionary-like
object -- as the session, thus allowing arbitrary data to be
inserted into a session so long as the attacker knows the
session key.
Denial of service attack via URLField
Django's model system includes a field type -- URLField --
which validates that the supplied value is a valid URL, and if
the boolean keyword argument verify_exists is true, attempts
to validate that the supplied URL also resolves, by issuing a
request to it.
By default, the underlying socket libraries in Python do not
have a timeout. This can manifest as a security problem in
three different ways:
- An attacker can supply a slow-to-respond URL. Each request
will tie up a server process for a period of time; if the
attacker is able to make enough requests, they can tie up
all available server processes.
- An attacker can supply a URL under his or her control, and
which will simply hold an open connection indefinitely. Due
to the lack of timeout, the Django process attempting to
verify the URL will similarly spin indefinitely. Repeating
this can easily tie up all available server processes.
- An attacker can supply a URL under his or her control
which not only keeps the connection open, but also sends an
unending stream of random garbage data. This data will
cause the memory usage of the Django process (which will
hold the response in memory) to grow without bound, thus
consuming not only server processes but also server
memory.
URLField redirection
The regular expression which validates URLs is used to check
the supplied URL before issuing a check to verify that it
exists, but if that URL issues a redirect in response to the
request, no validation of the resulting redirected URL is
performed, including basic checks for supported protocols
(HTTP, HTTPS, and FTP).
This creates a small window for an attacker to gain knowledge
of, for example, server layout; a redirect to a file:// URL,
for example, will tell an attacker whether a given file exists
locally on the server.
Additionally, although the initial request issued by Django
uses the HEAD method for HTTP/HTTPS, the request to the target
of the redirect is issued using GET. This may create further
issues for systems which implicitly trust GET requests from
the local machine/network.
Host header cache poisoning
In several places, Django itself -- independent of the
developer -- generates full URLs (for example, when issuing
HTTP redirects). Currently this uses the value of the HTTP
Host header from the request to construct the URL, which opens
a potential cache-poisoning vector: an attacker can submit
a request with a Host header of his or her choice, receive a
response which constructs URLs using that Host header, and --
if that response is cached -- further requests will be served
out of cache using URLs containing the attacker's host of
choice.