Fixed #30070, CVE-2019-3498 -- Fixed content spoofing possiblity in the default 404 page.
Co-Authored-By: Tim Graham <timograham@gmail.com>
This commit is contained in:
parent
e49ab72637
commit
1ecc0a395b
|
@ -1,3 +1,5 @@
|
||||||
|
from urllib.parse import quote
|
||||||
|
|
||||||
from django.http import (
|
from django.http import (
|
||||||
HttpResponseBadRequest, HttpResponseForbidden, HttpResponseNotFound,
|
HttpResponseBadRequest, HttpResponseForbidden, HttpResponseNotFound,
|
||||||
HttpResponseServerError,
|
HttpResponseServerError,
|
||||||
|
@ -22,7 +24,8 @@ def page_not_found(request, exception, template_name=ERROR_404_TEMPLATE_NAME):
|
||||||
Templates: :template:`404.html`
|
Templates: :template:`404.html`
|
||||||
Context:
|
Context:
|
||||||
request_path
|
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
|
exception
|
||||||
The message from the exception which triggered the 404 (if one was
|
The message from the exception which triggered the 404 (if one was
|
||||||
supplied), or the exception class name
|
supplied), or the exception class name
|
||||||
|
@ -38,7 +41,7 @@ def page_not_found(request, exception, template_name=ERROR_404_TEMPLATE_NAME):
|
||||||
if isinstance(message, str):
|
if isinstance(message, str):
|
||||||
exception_repr = message
|
exception_repr = message
|
||||||
context = {
|
context = {
|
||||||
'request_path': request.path,
|
'request_path': quote(request.path),
|
||||||
'exception': exception_repr,
|
'exception': exception_repr,
|
||||||
}
|
}
|
||||||
try:
|
try:
|
||||||
|
@ -51,7 +54,7 @@ def page_not_found(request, exception, template_name=ERROR_404_TEMPLATE_NAME):
|
||||||
raise
|
raise
|
||||||
template = Engine().from_string(
|
template = Engine().from_string(
|
||||||
'<h1>Not Found</h1>'
|
'<h1>Not Found</h1>'
|
||||||
'<p>The requested URL {{ request_path }} was not found on this server.</p>')
|
'<p>The requested resource was not found on this server.</p>')
|
||||||
body = template.render(Context(context))
|
body = template.render(Context(context))
|
||||||
content_type = 'text/html'
|
content_type = 'text/html'
|
||||||
return HttpResponseNotFound(body, content_type=content_type)
|
return HttpResponseNotFound(body, content_type=content_type)
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
============================
|
||||||
|
Django 1.11.18 release notes
|
||||||
|
============================
|
||||||
|
|
||||||
|
*January 4, 2019*
|
||||||
|
|
||||||
|
Django 1.11.18 fixes a security issue in 1.11.17.
|
||||||
|
|
||||||
|
CVE-2019-3498: Content spoofing possibility in the default 404 page
|
||||||
|
-------------------------------------------------------------------
|
||||||
|
|
||||||
|
An attacker could craft a malicious URL that could make spoofed content appear
|
||||||
|
on the default page generated by the ``django.views.defaults.page_not_found()``
|
||||||
|
view.
|
||||||
|
|
||||||
|
The URL path is no longer displayed in the default 404 template and the
|
||||||
|
``request_path`` context variable is now quoted to fix the issue for custom
|
||||||
|
templates that use the path.
|
|
@ -2,9 +2,20 @@
|
||||||
Django 2.0.10 release notes
|
Django 2.0.10 release notes
|
||||||
===========================
|
===========================
|
||||||
|
|
||||||
*Release date TBD*
|
*January 4, 2019*
|
||||||
|
|
||||||
Django 2.0.10 fixes several bugs in 2.0.9.
|
Django 2.0.10 fixes a security issue and several bugs in 2.0.9.
|
||||||
|
|
||||||
|
CVE-2019-3498: Content spoofing possibility in the default 404 page
|
||||||
|
-------------------------------------------------------------------
|
||||||
|
|
||||||
|
An attacker could craft a malicious URL that could make spoofed content appear
|
||||||
|
on the default page generated by the ``django.views.defaults.page_not_found()``
|
||||||
|
view.
|
||||||
|
|
||||||
|
The URL path is no longer displayed in the default 404 template and the
|
||||||
|
``request_path`` context variable is now quoted to fix the issue for custom
|
||||||
|
templates that use the path.
|
||||||
|
|
||||||
Bugfixes
|
Bugfixes
|
||||||
========
|
========
|
||||||
|
|
|
@ -2,10 +2,20 @@
|
||||||
Django 2.1.5 release notes
|
Django 2.1.5 release notes
|
||||||
==========================
|
==========================
|
||||||
|
|
||||||
*Expected January 1, 2019*
|
*January 4, 2019*
|
||||||
|
|
||||||
|
Django 2.1.5 fixes a security issue and several bugs in 2.1.4.
|
||||||
|
|
||||||
Django 2.1.5 fixes several bugs in 2.1.4.
|
CVE-2019-3498: Content spoofing possibility in the default 404 page
|
||||||
|
-------------------------------------------------------------------
|
||||||
|
|
||||||
|
An attacker could craft a malicious URL that could make spoofed content appear
|
||||||
|
on the default page generated by the ``django.views.defaults.page_not_found()``
|
||||||
|
view.
|
||||||
|
|
||||||
|
The URL path is no longer displayed in the default 404 template and the
|
||||||
|
``request_path`` context variable is now quoted to fix the issue for custom
|
||||||
|
templates that use the path.
|
||||||
|
|
||||||
Bugfixes
|
Bugfixes
|
||||||
========
|
========
|
||||||
|
|
|
@ -61,6 +61,7 @@ versions of the documentation contain the release notes for any later releases.
|
||||||
.. toctree::
|
.. toctree::
|
||||||
:maxdepth: 1
|
:maxdepth: 1
|
||||||
|
|
||||||
|
1.11.18
|
||||||
1.11.17
|
1.11.17
|
||||||
1.11.16
|
1.11.16
|
||||||
1.11.15
|
1.11.15
|
||||||
|
|
|
@ -5,6 +5,7 @@ from django.db import close_old_connections, connection
|
||||||
from django.test import (
|
from django.test import (
|
||||||
RequestFactory, SimpleTestCase, TransactionTestCase, override_settings,
|
RequestFactory, SimpleTestCase, TransactionTestCase, override_settings,
|
||||||
)
|
)
|
||||||
|
from django.utils.version import PY37
|
||||||
|
|
||||||
|
|
||||||
class HandlerTests(SimpleTestCase):
|
class HandlerTests(SimpleTestCase):
|
||||||
|
@ -162,16 +163,17 @@ class HandlerRequestTests(SimpleTestCase):
|
||||||
|
|
||||||
def test_invalid_urls(self):
|
def test_invalid_urls(self):
|
||||||
response = self.client.get('~%A9helloworld')
|
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/')
|
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/')
|
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/')
|
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):
|
def test_environ_path_info_type(self):
|
||||||
environ = self.request_factory.get('/%E2%A8%87%87%A5%E2%A8%A0').environ
|
environ = self.request_factory.get('/%E2%A8%87%87%A5%E2%A8%A0').environ
|
||||||
|
|
Loading…
Reference in New Issue