From a1f948b468b6621083a03b0d53432341b7a4d753 Mon Sep 17 00:00:00 2001 From: Tim Graham Date: Tue, 14 Mar 2017 12:33:15 -0400 Subject: [PATCH] Fixed CVE-2017-7234 -- Fixed open redirect vulnerability in views.static.serve(). This is a security fix. --- django/views/static.py | 22 ++++------------------ docs/releases/1.10.7.txt | 11 +++++++++++ docs/releases/1.8.18.txt | 11 +++++++++++ docs/releases/1.9.13.txt | 11 +++++++++++ tests/view_tests/tests/test_static.py | 2 +- 5 files changed, 38 insertions(+), 19 deletions(-) diff --git a/django/views/static.py b/django/views/static.py index 03e8c34a1c..289d26ef55 100644 --- a/django/views/static.py +++ b/django/views/static.py @@ -10,9 +10,9 @@ import stat from django.http import ( FileResponse, Http404, HttpResponse, HttpResponseNotModified, - HttpResponseRedirect, ) from django.template import Context, Engine, TemplateDoesNotExist, loader +from django.utils._os import safe_join from django.utils.http import http_date, parse_http_date from django.utils.translation import gettext as _, gettext_lazy @@ -33,25 +33,11 @@ def serve(request, path, document_root=None, show_indexes=False): but if you'd like to override it, you can create a template called ``static/directory_index.html``. """ - path = posixpath.normpath(path) - path = path.lstrip('/') - newpath = '' - for part in path.split('/'): - if not part: - # Strip empty path components. - continue - drive, part = os.path.splitdrive(part) - head, part = os.path.split(part) - if part in (os.curdir, os.pardir): - # Strip '.' and '..' in path. - continue - newpath = os.path.join(newpath, part).replace('\\', '/') - if newpath and path != newpath: - return HttpResponseRedirect(newpath) - fullpath = os.path.join(document_root, newpath) + path = posixpath.normpath(path).lstrip('/') + fullpath = safe_join(document_root, path) if os.path.isdir(fullpath): if show_indexes: - return directory_index(newpath, fullpath) + return directory_index(path, fullpath) raise Http404(_("Directory indexes are not allowed here.")) if not os.path.exists(fullpath): raise Http404(_('"%(path)s" does not exist') % {'path': fullpath}) diff --git a/docs/releases/1.10.7.txt b/docs/releases/1.10.7.txt index 630610e0af..0c79347cc3 100644 --- a/docs/releases/1.10.7.txt +++ b/docs/releases/1.10.7.txt @@ -6,6 +6,17 @@ Django 1.10.7 release notes Django 1.10.7 fixes two security issues and a bug in 1.10.6. +CVE-2017-7234: Open redirect vulnerability in ``django.views.static.serve()`` +============================================================================= + +A maliciously crafted URL to a Django site using the +:func:`~django.views.static.serve` view could redirect to any other domain. The +view no longer does any redirects as they don't provide any known, useful +functionality. + +Note, however, that this view has always carried a warning that it is not +hardened for production use and should be used only as a development aid. + Bugfixes ======== diff --git a/docs/releases/1.8.18.txt b/docs/releases/1.8.18.txt index 92492c7825..7b1e08046c 100644 --- a/docs/releases/1.8.18.txt +++ b/docs/releases/1.8.18.txt @@ -5,3 +5,14 @@ Django 1.8.18 release notes *April 4, 2017* Django 1.8.18 fixes two security issues in 1.8.17. + +CVE-2017-7234: Open redirect vulnerability in ``django.views.static.serve()`` +============================================================================= + +A maliciously crafted URL to a Django site using the +:func:`~django.views.static.serve` view could redirect to any other domain. The +view no longer does any redirects as they don't provide any known, useful +functionality. + +Note, however, that this view has always carried a warning that it is not +hardened for production use and should be used only as a development aid. diff --git a/docs/releases/1.9.13.txt b/docs/releases/1.9.13.txt index 42f22a8f00..f9d203eafe 100644 --- a/docs/releases/1.9.13.txt +++ b/docs/releases/1.9.13.txt @@ -7,6 +7,17 @@ Django 1.9.13 release notes Django 1.9.13 fixes two security issues and a bug in 1.9.12. This is the final release of the 1.9.x series. +CVE-2017-7234: Open redirect vulnerability in ``django.views.static.serve()`` +============================================================================= + +A maliciously crafted URL to a Django site using the +:func:`~django.views.static.serve` view could redirect to any other domain. The +view no longer does any redirects as they don't provide any known, useful +functionality. + +Note, however, that this view has always carried a warning that it is not +hardened for production use and should be used only as a development aid. + Bugfixes ======== diff --git a/tests/view_tests/tests/test_static.py b/tests/view_tests/tests/test_static.py index 39ddc6b878..0d3b599767 100644 --- a/tests/view_tests/tests/test_static.py +++ b/tests/view_tests/tests/test_static.py @@ -110,7 +110,7 @@ class StaticTests(SimpleTestCase): def test_index(self): response = self.client.get('/%s/' % self.prefix) - self.assertContains(response, 'Index of /') + self.assertContains(response, 'Index of ./') class StaticHelperTest(StaticTests):