diff --git a/debian/changelog b/debian/changelog index b1c56f7c5..fa89c8b21 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,10 @@ +python-django (1:1.10.7-2+deb9u4) stretch-security; urgency=high + + * CVE-2019-3498: Prevent a content-spoofing vulnerability in the default + 404 page. (Closes: #918230) + + -- Chris Lamb Sun, 06 Jan 2019 09:35:11 +0100 + python-django (1:1.10.7-2+deb9u3) stretch; urgency=medium * Default to supporting Spatialite >= 4.2. (Closes: #910240) diff --git a/debian/patches/0017-CVE-2019-3498.patch b/debian/patches/0017-CVE-2019-3498.patch new file mode 100644 index 000000000..588db30a8 --- /dev/null +++ b/debian/patches/0017-CVE-2019-3498.patch @@ -0,0 +1,95 @@ +From: Tom Hacohen +Date: Fri, 4 Jan 2019 02:21:55 +0000 +Subject: Fixed #30070, + CVE-2019-3498 -- Fixed content spoofing possiblity in the default 404 page. + +Co-Authored-By: Tim Graham +Backport of 1ecc0a395be721e987e8e9fdfadde952b6dee1c7 from master. +--- + django/views/defaults.py | 8 +++++--- + tests/handlers/tests.py | 12 ++++++++---- + 2 files changed, 13 insertions(+), 7 deletions(-) + +diff --git a/django/views/defaults.py b/django/views/defaults.py +index 348837e..5ec9ac8 100644 +--- a/django/views/defaults.py ++++ b/django/views/defaults.py +@@ -2,6 +2,7 @@ from django import http + from django.template import Context, Engine, TemplateDoesNotExist, loader + from django.utils import six + from django.utils.encoding import force_text ++from django.utils.http import urlquote + from django.views.decorators.csrf import requires_csrf_token + + ERROR_404_TEMPLATE_NAME = '404.html' +@@ -21,7 +22,8 @@ def page_not_found(request, exception, template_name=ERROR_404_TEMPLATE_NAME): + Templates: :template:`404.html` + Context: + request_path +- The path of the requested URL (e.g., '/app/pages/bad_page/') ++ The path of the requested URL (e.g., '/app/pages/bad_page/'). It's ++ quoted to prevent a content injection attack. + exception + The message from the exception which triggered the 404 (if one was + supplied), or the exception class name +@@ -37,7 +39,7 @@ def page_not_found(request, exception, template_name=ERROR_404_TEMPLATE_NAME): + if isinstance(message, six.text_type): + exception_repr = message + context = { +- 'request_path': request.path, ++ 'request_path': urlquote(request.path), + 'exception': exception_repr, + } + try: +@@ -50,7 +52,7 @@ def page_not_found(request, exception, template_name=ERROR_404_TEMPLATE_NAME): + raise + template = Engine().from_string( + '

Not Found

' +- '

The requested URL {{ request_path }} was not found on this server.

') ++ '

The requested resource was not found on this server.

') + body = template.render(Context(context)) + content_type = 'text/html' + return http.HttpResponseNotFound(body, content_type=content_type) +diff --git a/tests/handlers/tests.py b/tests/handlers/tests.py +index 9f01cb2..50a3488 100644 +--- a/tests/handlers/tests.py ++++ b/tests/handlers/tests.py +@@ -2,6 +2,7 @@ + + from __future__ import unicode_literals + ++import sys + import unittest + + from django.core.exceptions import ImproperlyConfigured +@@ -19,6 +20,8 @@ try: + except ImportError: # Python < 3.5 + HTTPStatus = None + ++PY37 = sys.version_info >= (3, 7, 0) ++ + + class HandlerTests(SimpleTestCase): + +@@ -180,16 +183,17 @@ class HandlerRequestTests(SimpleTestCase): + + def test_invalid_urls(self): + response = self.client.get('~%A9helloworld') +- self.assertContains(response, '~%A9helloworld', status_code=404) ++ self.assertEqual(response.status_code, 404) ++ self.assertEqual(response.context['request_path'], '/~%25A9helloworld' if PY37 else '/%7E%25A9helloworld') + + response = self.client.get('d%aao%aaw%aan%aal%aao%aaa%aad%aa/') +- self.assertContains(response, 'd%AAo%AAw%AAn%AAl%AAo%AAa%AAd%AA', status_code=404) ++ self.assertEqual(response.context['request_path'], '/d%25AAo%25AAw%25AAn%25AAl%25AAo%25AAa%25AAd%25AA') + + response = self.client.get('/%E2%99%E2%99%A5/') +- self.assertContains(response, '%E2%99\u2665', status_code=404) ++ self.assertEqual(response.context['request_path'], '/%25E2%2599%E2%99%A5/') + + response = self.client.get('/%E2%98%8E%E2%A9%E2%99%A5/') +- self.assertContains(response, '\u260e%E2%A9\u2665', status_code=404) ++ self.assertEqual(response.context['request_path'], '/%E2%98%8E%25E2%25A9%E2%99%A5/') + + def test_environ_path_info_type(self): + environ = RequestFactory().get('/%E2%A8%87%87%A5%E2%A8%A0').environ diff --git a/debian/patches/series b/debian/patches/series index 6ccbb746a..5bda383eb 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -8,3 +8,4 @@ fix-test-middleware-classes-headers.patch 0015-CVE-2018-14574.patch 0016-CVE-2017-12794.patch 0006-Default-to-supporting-Spatialite-4.2.patch +0017-CVE-2019-3498.patch