티스토리 수익 글 보기

티스토리 수익 글 보기

[2.0.x] Fixed #30070, CVE-2019-3498 — Fixed content spoofing possibl… · django/django@9f4ed7c · GitHub
Skip to content

Commit 9f4ed7c

Browse files
tasntimgraham
andcommitted
[2.0.x] Fixed #30070, CVE-2019-3498 — Fixed content spoofing possiblity in the default 404 page.
Co-Authored-By: Tim Graham <timograham@gmail.com> Backport of 1ecc0a3 from master.
1 parent f167f30 commit 9f4ed7c

File tree

5 files changed

+46
9
lines changed

5 files changed

+46
9
lines changed

django/views/defaults.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from urllib.parse import quote
2+
13
from django.http import (
24
HttpResponseBadRequest, HttpResponseForbidden, HttpResponseNotFound,
35
HttpResponseServerError,
@@ -22,7 +24,8 @@ def page_not_found(request, exception, template_name=ERROR_404_TEMPLATE_NAME):
2224
Templates: :template:`404.html`
2325
Context:
2426
request_path
25-
The path of the requested URL (e.g., '/app/pages/bad_page/')
27+
The path of the requested URL (e.g., '/app/pages/bad_page/'). It's
28+
quoted to prevent a content injection attack.
2629
exception
2730
The message from the exception which triggered the 404 (if one was
2831
supplied), or the exception class name
@@ -38,7 +41,7 @@ def page_not_found(request, exception, template_name=ERROR_404_TEMPLATE_NAME):
3841
if isinstance(message, str):
3942
exception_repr = message
4043
context = {
41-
'request_path': request.path,
44+
'request_path': quote(request.path),
4245
'exception': exception_repr,
4346
}
4447
try:
@@ -51,7 +54,7 @@ def page_not_found(request, exception, template_name=ERROR_404_TEMPLATE_NAME):
5154
raise
5255
template = Engine().from_string(
5356
'<h1>Not Found</h1>'
54-
'<p>The requested URL {{ request_path }} was not found on this server.</p>')
57+
'<p>The requested resource was not found on this server.</p>')
5558
body = template.render(Context(context))
5659
content_type = 'text/html'
5760
return HttpResponseNotFound(body, content_type=content_type)

docs/releases/1.11.18.txt

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
============================
2+
Django 1.11.18 release notes
3+
============================
4+
5+
*January 4, 2019*
6+
7+
Django 1.11.18 fixes a security issue in 1.11.17.
8+
9+
CVE-2019-3498: Content spoofing possibility in the default 404 page
10+
-------------------------------------------------------------------
11+
12+
An attacker could craft a malicious URL that could make spoofed content appear
13+
on the default page generated by the ``django.views.defaults.page_not_found()``
14+
view.
15+
16+
The URL path is no longer displayed in the default 404 template and the
17+
``request_path`` context variable is now quoted to fix the issue for custom
18+
templates that use the path.

docs/releases/2.0.10.txt

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,20 @@
22
Django 2.0.10 release notes
33
===========================
44

5-
*Release date TBD*
5+
*January 4, 2019*
66

7-
Django 2.0.10 fixes several bugs in 2.0.9.
7+
Django 2.0.10 fixes a security issue and several bugs in 2.0.9.
8+
9+
CVE-2019-3498: Content spoofing possibility in the default 404 page
10+
-------------------------------------------------------------------
11+
12+
An attacker could craft a malicious URL that could make spoofed content appear
13+
on the default page generated by the ``django.views.defaults.page_not_found()``
14+
view.
15+
16+
The URL path is no longer displayed in the default 404 template and the
17+
``request_path`` context variable is now quoted to fix the issue for custom
18+
templates that use the path.
819

920
Bugfixes
1021
========

docs/releases/index.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ versions of the documentation contain the release notes for any later releases.
4242
.. toctree::
4343
:maxdepth: 1
4444

45+
1.11.18
4546
1.11.17
4647
1.11.16
4748
1.11.15

tests/handlers/tests.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import sys
12
import unittest
23

34
from django.core.exceptions import ImproperlyConfigured
@@ -13,6 +14,8 @@
1314
except ImportError: # Python < 3.5
1415
HTTPStatus = None
1516

17+
PY37 = sys.version_info >= (3, 7, 0)
18+
1619

1720
class HandlerTests(SimpleTestCase):
1821

@@ -167,16 +170,17 @@ def test_suspiciousop_in_view_returns_400(self):
167170

168171
def test_invalid_urls(self):
169172
response = self.client.get('~%A9helloworld')
170-
self.assertContains(response, '~%A9helloworld', status_code=404)
173+
self.assertEqual(response.status_code, 404)
174+
self.assertEqual(response.context['request_path'], '/~%25A9helloworld' if PY37 else '/%7E%25A9helloworld')
171175

172176
response = self.client.get('d%aao%aaw%aan%aal%aao%aaa%aad%aa/')
173-
self.assertContains(response, 'd%AAo%AAw%AAn%AAl%AAo%AAa%AAd%AA', status_code=404)
177+
self.assertEqual(response.context['request_path'], '/d%25AAo%25AAw%25AAn%25AAl%25AAo%25AAa%25AAd%25AA')
174178

175179
response = self.client.get('/%E2%99%E2%99%A5/')
176-
self.assertContains(response, '%E2%99\u2665', status_code=404)
180+
self.assertEqual(response.context['request_path'], '/%25E2%2599%E2%99%A5/')
177181

178182
response = self.client.get('/%E2%98%8E%E2%A9%E2%99%A5/')
179-
self.assertContains(response, '\u260e%E2%A9\u2665', status_code=404)
183+
self.assertEqual(response.context['request_path'], '/%E2%98%8E%25E2%25A9%E2%99%A5/')
180184

181185
def test_environ_path_info_type(self):
182186
environ = RequestFactory().get('/%E2%A8%87%87%A5%E2%A8%A0').environ

0 commit comments

Comments
 (0)