[Python-modules-commits] r9207 - in packages/python-django/branches/lenny/debian (2 files)
lamby at users.alioth.debian.org
lamby at users.alioth.debian.org
Wed Jul 29 12:08:10 UTC 2009
Date: Wednesday, July 29, 2009 @ 12:07:50
Author: lamby
Revision: 9207
Add patch to fix issue with a maliciously crafted URL gaining access to any file on the filesystem (Closes: #539134)
Added:
packages/python-django/branches/lenny/debian/patches/01-539134-sanitise-static-media.diff
Modified:
packages/python-django/branches/lenny/debian/changelog
Modified: packages/python-django/branches/lenny/debian/changelog
===================================================================
--- packages/python-django/branches/lenny/debian/changelog 2009-07-29 11:09:45 UTC (rev 9206)
+++ packages/python-django/branches/lenny/debian/changelog 2009-07-29 12:07:50 UTC (rev 9207)
@@ -1,3 +1,25 @@
+python-django (1.0.2-1+lenny1) stable-security; urgency=high
+
+ * Add patch to fix issue with a maliciously crafted URL gaining access to
+ any file on the filesystem (Closes: #539134)
+
+ Upstream writes:
+
+ Django includes a lightweight, WSGI-based web server for use in
+ learning Django and in testing new applications during early stages of
+ development. For sake of convenience, this web server automatically
+ maps certain URLs corresponding to the static media files used by the
+ Django administrative application.
+
+ The handler which maps these URLs did not properly check the requested
+ URL to verify that it corresponds to a static media file used by
+ Django. As such, a carefully-crafted URL can cause the development
+ server to serve any file to which it has read access.
+
+ <http://www.djangoproject.com/weblog/2009/jul/28/security/>
+
+ -- Chris Lamb <lamby at debian.org> Wed, 29 Jul 2009 13:11:14 +0200
+
python-django (1.0.2-1) unstable; urgency=low
[ Chris Lamb ]
Added: packages/python-django/branches/lenny/debian/patches/01-539134-sanitise-static-media.diff
===================================================================
--- packages/python-django/branches/lenny/debian/patches/01-539134-sanitise-static-media.diff (rev 0)
+++ packages/python-django/branches/lenny/debian/patches/01-539134-sanitise-static-media.diff 2009-07-29 12:07:50 UTC (rev 9207)
@@ -0,0 +1,149 @@
+Source: http://code.djangoproject.com/changeset/11353
+
+ -- Chris Lamb <lamby at debian.org> Wed, 29 Jul 2009 13:17:43 +0200
+
+Index: ./django/core/servers/basehttp.py
+===================================================================
+--- ./django/core/servers/basehttp.py (revision 10691)
++++ ./django/core/servers/basehttp.py (revision 11353)
+@@ -17,4 +17,5 @@
+
+ from django.utils.http import http_date
++from django.utils._os import safe_join
+
+ __version__ = "0.1"
+@@ -622,8 +623,22 @@
+ if not media_dir:
+ import django
+- self.media_dir = django.__path__[0] + '/contrib/admin/media'
++ self.media_dir = \
++ os.path.join(django.__path__[0], 'contrib', 'admin', 'media')
+ else:
+ self.media_dir = media_dir
+ self.media_url = settings.ADMIN_MEDIA_PREFIX
++
++ def file_path(self, url):
++ """
++ Returns the path to the media file on disk for the given URL.
++
++ The passed URL is assumed to begin with ADMIN_MEDIA_PREFIX. If the
++ resultant file path is outside the media directory, then a ValueError
++ is raised.
++ """
++ # Remove ADMIN_MEDIA_PREFIX.
++ relative_url = url[len(self.media_url):]
++ relative_path = urllib.url2pathname(relative_url)
++ return safe_join(self.media_dir, relative_path)
+
+ def __call__(self, environ, start_response):
+@@ -637,10 +652,16 @@
+
+ # Find the admin file and serve it up, if it exists and is readable.
+- relative_url = environ['PATH_INFO'][len(self.media_url):]
+- file_path = os.path.join(self.media_dir, relative_url)
++ try:
++ file_path = self.file_path(environ['PATH_INFO'])
++ except ValueError: # Resulting file path was not valid.
++ status = '404 NOT FOUND'
++ headers = {'Content-type': 'text/plain'}
++ output = ['Page not found: %s' % environ['PATH_INFO']]
++ start_response(status, headers.items())
++ return output
+ if not os.path.exists(file_path):
+ status = '404 NOT FOUND'
+ headers = {'Content-type': 'text/plain'}
+- output = ['Page not found: %s' % file_path]
++ output = ['Page not found: %s' % environ['PATH_INFO']]
+ else:
+ try:
+@@ -649,5 +670,5 @@
+ status = '401 UNAUTHORIZED'
+ headers = {'Content-type': 'text/plain'}
+- output = ['Permission denied: %s' % file_path]
++ output = ['Permission denied: %s' % environ['PATH_INFO']]
+ else:
+ # This is a very simple implementation of conditional GET with
+Index: ./django/core/management/commands/runserver.py
+===================================================================
+--- ./django/core/management/commands/runserver.py (revision 8749)
++++ ./django/core/management/commands/runserver.py (revision 11353)
+@@ -57,6 +57,5 @@
+
+ try:
+- path = admin_media_path or django.__path__[0] + '/contrib/admin/media'
+- handler = AdminMediaHandler(WSGIHandler(), path)
++ handler = AdminMediaHandler(WSGIHandler(), admin_media_path)
+ run(addr, int(port), handler)
+ except WSGIServerException, e:
+Index: ./tests/regressiontests/servers/tests.py
+===================================================================
+--- ./tests/regressiontests/servers/tests.py (revision 11353)
++++ ./tests/regressiontests/servers/tests.py (revision 11353)
+@@ -0,0 +1,67 @@
++"""
++Tests for django.core.servers.
++"""
++
++import os
++
++import django
++from django.test import TestCase
++from django.core.handlers.wsgi import WSGIHandler
++from django.core.servers.basehttp import AdminMediaHandler
++
++
++class AdminMediaHandlerTests(TestCase):
++
++ def setUp(self):
++ self.admin_media_file_path = \
++ os.path.join(django.__path__[0], 'contrib', 'admin', 'media')
++ self.handler = AdminMediaHandler(WSGIHandler())
++
++ def test_media_urls(self):
++ """
++ Tests that URLs that look like absolute file paths after the
++ settings.ADMIN_MEDIA_PREFIX don't turn into absolute file paths.
++ """
++ # Cases that should work on all platforms.
++ data = (
++ ('/media/css/base.css', ('css', 'base.css')),
++ )
++ # Cases that should raise an exception.
++ bad_data = ()
++
++ # Add platform-specific cases.
++ if os.sep == '/':
++ data += (
++ # URL, tuple of relative path parts.
++ ('/media/\\css/base.css', ('\\css', 'base.css')),
++ )
++ bad_data += (
++ '/media//css/base.css',
++ '/media////css/base.css',
++ '/media/../css/base.css',
++ )
++ elif os.sep == '\\':
++ bad_data += (
++ '/media/C:\css/base.css',
++ '/media//\\css/base.css',
++ '/media/\\css/base.css',
++ '/media/\\\\css/base.css'
++ )
++ for url, path_tuple in data:
++ try:
++ output = self.handler.file_path(url)
++ except ValueError:
++ self.fail("Got a ValueError exception, but wasn't expecting"
++ " one. URL was: %s" % url)
++ rel_path = os.path.join(*path_tuple)
++ desired = os.path.normcase(
++ os.path.join(self.admin_media_file_path, rel_path))
++ self.assertEqual(output, desired,
++ "Got: %s, Expected: %s, URL was: %s" % (output, desired, url))
++ for url in bad_data:
++ try:
++ output = self.handler.file_path(url)
++ except ValueError:
++ continue
++ self.fail('URL: %s should have caused a ValueError exception.'
++ % url)
More information about the Python-modules-commits
mailing list