+32
-7
lines changedFilter options
+32
-7
lines changed Original file line number Diff line number Diff line change
@@ -2,6 +2,7 @@
2
2
from django.template import Context, Engine, TemplateDoesNotExist, loader
3
3
from django.utils import six
4
4
from django.utils.encoding import force_text
5
+
from django.utils.http import urlquote
5
6
from django.views.decorators.csrf import requires_csrf_token
6
7
7
8
ERROR_404_TEMPLATE_NAME = '404.html'
@@ -21,7 +22,8 @@ def page_not_found(request, exception, template_name=ERROR_404_TEMPLATE_NAME):
21
22
Templates: :template:`404.html`
22
23
Context:
23
24
request_path
24
-
The path of the requested URL (e.g., '/app/pages/bad_page/')
25
+
The path of the requested URL (e.g., '/app/pages/bad_page/'). It's
26
+
quoted to prevent a content injection attack.
25
27
exception
26
28
The message from the exception which triggered the 404 (if one was
27
29
supplied), or the exception class name
@@ -37,7 +39,7 @@ def page_not_found(request, exception, template_name=ERROR_404_TEMPLATE_NAME):
37
39
if isinstance(message, six.text_type):
38
40
exception_repr = message
39
41
context = {
40
-
'request_path': request.path,
42
+
'request_path': urlquote(request.path),
41
43
'exception': exception_repr,
42
44
}
43
45
try:
@@ -50,7 +52,7 @@ def page_not_found(request, exception, template_name=ERROR_404_TEMPLATE_NAME):
50
52
raise
51
53
template = Engine().from_string(
52
54
'<h1>Not Found</h1>'
53
-
'<p>The requested URL {{ request_path }} was not found on this server.</p>')
55
+
'<p>The requested resource was not found on this server.</p>')
54
56
body = template.render(Context(context))
55
57
content_type = 'text/html'
56
58
return http.HttpResponseNotFound(body, content_type=content_type)
Original file line number Diff line number Diff 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.
Original file line number Diff line number Diff line change
@@ -26,6 +26,7 @@ versions of the documentation contain the release notes for any later releases.
26
26
.. toctree::
27
27
:maxdepth: 1
28
28
29
+
1.11.18
29
30
1.11.17
30
31
1.11.16
31
32
1.11.15
Original file line number Diff line number Diff line change
@@ -2,6 +2,7 @@
2
2
3
3
from __future__ import unicode_literals
4
4
5
+
import sys
5
6
import unittest
6
7
7
8
from django.core.exceptions import ImproperlyConfigured
@@ -19,6 +20,8 @@
19
20
except ImportError: # Python < 3.5
20
21
HTTPStatus = None
21
22
23
+
PY37 = sys.version_info >= (3, 7, 0)
24
+
22
25
23
26
class HandlerTests(SimpleTestCase):
24
27
@@ -184,16 +187,17 @@ def test_suspiciousop_in_view_returns_400(self):
184
187
185
188
def test_invalid_urls(self):
186
189
response = self.client.get('~%A9helloworld')
187
-
self.assertContains(response, '~%A9helloworld', status_code=404)
190
+
self.assertEqual(response.status_code, 404)
191
+
self.assertEqual(response.context['request_path'], '/~%25A9helloworld' if PY37 else '/%7E%25A9helloworld')
188
192
189
193
response = self.client.get('d%aao%aaw%aan%aal%aao%aaa%aad%aa/')
190
-
self.assertContains(response, 'd%AAo%AAw%AAn%AAl%AAo%AAa%AAd%AA', status_code=404)
194
+
self.assertEqual(response.context['request_path'], '/d%25AAo%25AAw%25AAn%25AAl%25AAo%25AAa%25AAd%25AA')
191
195
192
196
response = self.client.get('/%E2%99%E2%99%A5/')
193
-
self.assertContains(response, '%E2%99\u2665', status_code=404)
197
+
self.assertEqual(response.context['request_path'], '/%25E2%2599%E2%99%A5/')
194
198
195
199
response = self.client.get('/%E2%98%8E%E2%A9%E2%99%A5/')
196
-
self.assertContains(response, '\u260e%E2%A9\u2665', status_code=404)
200
+
self.assertEqual(response.context['request_path'], '/%E2%98%8E%25E2%25A9%E2%99%A5/')
197
201
198
202
def test_environ_path_info_type(self):
199
203
environ = RequestFactory().get('/%E2%A8%87%87%A5%E2%A8%A0').environ
You can’t perform that action at this time.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4