Security releases issued
Today the Django team is issuing multiple releases -- Django 1.2.4, Django 1.1.3 and Django 1.3 beta 1 -- to remedy two security issues reported to us. All users of affected versions of Django are urged to upgrade immediately.
Information leakage in Django administrative interface
The Django administrative interface, django.contrib.admin
, supports
filtering of displayed lists of objects by fields on the corresponding
models, including across database-level relationships. This is
implemented by passing lookup arguments in the querystring portion of
the URL, and options on the ModelAdmin
class allow developers to
specify particular fields or relationships which will generate
automatic links for filtering.
One historically-undocumented and -unofficially-supported feature has been the ability for a user with sufficient knowledge of a model's structure and the format of these lookup arguments to invent useful new filters on the fly by manipulating the querystring.
As reported to us by Adam Baldwin, however, this can be abused to gain access to information outside of an admin user's permissions; for example, an attacker with access to the admin and sufficient knowledge of model structure and relations could construct querystrings which -- with repeated use of regular-expression lookups supported by the Django database API -- expose sensitive information such as users' password hashes.
To remedy this, django.contrib.admin
will now validate that
querystring lookup arguments either specify only fields on the model
being viewed, or cross relations which have been explicitly
whitelisted by the application developer using the pre-existing
mechanism mentioned above. This is backwards-incompatible for any
users relying on the prior ability to insert arbitrary lookups, but as
this "feature" was never documented or supported, we do not consider
it to be an issue for our API-stability policy. The release notes for
Django 1.3 beta 1 -- which will include this change -- will, however,
note this difference from previous Django releases.
Denial-of-service attack in password-reset mechanism
Django's bundled authentication framework, django.contrib.auth
, offers
views which allow users to reset a forgotten password. The reset
mechanism involves generating a one-time token composed from the
user's ID, the timestamp of the reset request converted to a base36
integer, and a hash derived from the user's current password hash
(which will change once the reset is complete, thus invalidating the
token).
The code which verifies this token, however, does not validate the length of the supplied base36 timestamp before attempting to convert it. An attacker with sufficient knowledge of a site's URL configuration and the manner in which the reset token is constructed can, then, craft a request containing an arbitrarily-large (up to the web server's maximum supported URL length) base36 integer, which Django will blindly attempt to convert back into a timestamp.
As reported to us by Paul McMillan, the time required to attempt this conversion on ever-larger numbers will consume significant server resources, and many such simultaneous requests will result in an effective denial-of-service attack. Further investigation revealed that the password-reset code blindly converts base36 in multiple places.
To remedy this, the base36_to_int()
function in django.utils.http
will
now validate the length of its input; on input longer than 13 digits
(sufficient to base36-encode any 64-bit integer), it will now raise
ValueError. Additionally, the default URL patterns for
django.contrib.auth
will now enforce a maximum length on the relevant
parameters.
Affected versions
Both of the issues described above are present in the following currently-supported Django versions:
- Django development trunk
- Django 1.2
- Django 1.1
Resolution
Patches have been applied to Django trunk, and to the 1.2 and 1.1 release branches, which resolve both issues described above. The patches may be obtained directly from the appropriate changesets:
- Django trunk: changeset 15031 for the admin issue and changeset 15032 for the password-token issue.
- Django 1.2: changeset 15033 for the admin issue and changeset 15034 for the password-token issue.
- Django 1.1: changeset 15035 for the admin issue and changeset 15036 for the password-token issue.
The following new releases have been issued:
Django 1.3 beta 1, which will contain the patch from Django trunk, will also be issued later today.
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
Due to the impending Christmas and New Year's holiday, our normal process of notifying distributors of Django one week in advance of security-releated release was shortened somewhat to allow these releases to be issued before most Django users take their holiday vacations.
If you are or represent a third-party distributor of Django and did
not receive a notification email from the Django release manager,
please contact james@b-list.org
.