diff --git a/django/views/static.py b/django/views/static.py index 9959b96236..9e4e916b57 100644 --- a/django/views/static.py +++ b/django/views/static.py @@ -12,9 +12,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.six.moves.urllib.parse import unquote from django.utils.translation import ugettext as _, ugettext_lazy @@ -36,25 +36,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(unquote(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(unquote(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.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.