Fixed CVE-2017-12794 -- Fixed XSS possibility in traceback section of technical 500 debug page.
This is a security fix.
This commit is contained in:
parent
73b6d02747
commit
46e2b9e059
|
@ -8,7 +8,7 @@ from pathlib import Path
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.http import HttpResponse, HttpResponseNotFound
|
from django.http import HttpResponse, HttpResponseNotFound
|
||||||
from django.template import Context, Engine, TemplateDoesNotExist
|
from django.template import Context, Engine, TemplateDoesNotExist
|
||||||
from django.template.defaultfilters import force_escape, pprint
|
from django.template.defaultfilters import pprint
|
||||||
from django.urls import Resolver404, resolve
|
from django.urls import Resolver404, resolve
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.utils.datastructures import MultiValueDict
|
from django.utils.datastructures import MultiValueDict
|
||||||
|
@ -271,7 +271,7 @@ class ExceptionReporter:
|
||||||
# Trim large blobs of data
|
# Trim large blobs of data
|
||||||
if len(v) > 4096:
|
if len(v) > 4096:
|
||||||
v = '%s... <trimmed %d bytes string>' % (v[0:4096], len(v))
|
v = '%s... <trimmed %d bytes string>' % (v[0:4096], len(v))
|
||||||
frame_vars.append((k, force_escape(v)))
|
frame_vars.append((k, v))
|
||||||
frame['vars'] = frame_vars
|
frame['vars'] = frame_vars
|
||||||
frames[i] = frame
|
frames[i] = frame
|
||||||
|
|
||||||
|
|
|
@ -212,38 +212,37 @@
|
||||||
<h2>Traceback <span class="commands">{% if not is_email %}<a href="#" onclick="return switchPastebinFriendly(this);">
|
<h2>Traceback <span class="commands">{% if not is_email %}<a href="#" onclick="return switchPastebinFriendly(this);">
|
||||||
Switch to copy-and-paste view</a></span>{% endif %}
|
Switch to copy-and-paste view</a></span>{% endif %}
|
||||||
</h2>
|
</h2>
|
||||||
{% autoescape off %}
|
|
||||||
<div id="browserTraceback">
|
<div id="browserTraceback">
|
||||||
<ul class="traceback">
|
<ul class="traceback">
|
||||||
{% for frame in frames %}
|
{% for frame in frames %}
|
||||||
{% ifchanged frame.exc_cause %}{% if frame.exc_cause %}
|
{% ifchanged frame.exc_cause %}{% if frame.exc_cause %}
|
||||||
<li><h3>
|
<li><h3>
|
||||||
{% if frame.exc_cause_explicit %}
|
{% if frame.exc_cause_explicit %}
|
||||||
The above exception ({{ frame.exc_cause }}) was the direct cause of the following exception:
|
The above exception ({{ frame.exc_cause|force_escape }}) was the direct cause of the following exception:
|
||||||
{% else %}
|
{% else %}
|
||||||
During handling of the above exception ({{ frame.exc_cause }}), another exception occurred:
|
During handling of the above exception ({{ frame.exc_cause|force_escape }}), another exception occurred:
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</h3></li>
|
</h3></li>
|
||||||
{% endif %}{% endifchanged %}
|
{% endif %}{% endifchanged %}
|
||||||
<li class="frame {{ frame.type }}">
|
<li class="frame {{ frame.type }}">
|
||||||
<code>{{ frame.filename|escape }}</code> in <code>{{ frame.function|escape }}</code>
|
<code>{{ frame.filename }}</code> in <code>{{ frame.function }}</code>
|
||||||
|
|
||||||
{% if frame.context_line %}
|
{% if frame.context_line %}
|
||||||
<div class="context" id="c{{ frame.id }}">
|
<div class="context" id="c{{ frame.id }}">
|
||||||
{% if frame.pre_context and not is_email %}
|
{% if frame.pre_context and not is_email %}
|
||||||
<ol start="{{ frame.pre_context_lineno }}" class="pre-context" id="pre{{ frame.id }}">
|
<ol start="{{ frame.pre_context_lineno }}" class="pre-context" id="pre{{ frame.id }}">
|
||||||
{% for line in frame.pre_context %}
|
{% for line in frame.pre_context %}
|
||||||
<li onclick="toggle('pre{{ frame.id }}', 'post{{ frame.id }}')"><pre>{{ line|escape }}</pre></li>
|
<li onclick="toggle('pre{{ frame.id }}', 'post{{ frame.id }}')"><pre>{{ line }}</pre></li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ol>
|
</ol>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<ol start="{{ frame.lineno }}" class="context-line">
|
<ol start="{{ frame.lineno }}" class="context-line">
|
||||||
<li onclick="toggle('pre{{ frame.id }}', 'post{{ frame.id }}')"><pre>{{ frame.context_line|escape }}</pre>{% if not is_email %} <span>...</span>{% endif %}</li>
|
<li onclick="toggle('pre{{ frame.id }}', 'post{{ frame.id }}')"><pre>{{ frame.context_line }}</pre>{% if not is_email %} <span>...</span>{% endif %}</li>
|
||||||
</ol>
|
</ol>
|
||||||
{% if frame.post_context and not is_email %}
|
{% if frame.post_context and not is_email %}
|
||||||
<ol start='{{ frame.lineno|add:"1" }}' class="post-context" id="post{{ frame.id }}">
|
<ol start='{{ frame.lineno|add:"1" }}' class="post-context" id="post{{ frame.id }}">
|
||||||
{% for line in frame.post_context %}
|
{% for line in frame.post_context %}
|
||||||
<li onclick="toggle('pre{{ frame.id }}', 'post{{ frame.id }}')"><pre>{{ line|escape }}</pre></li>
|
<li onclick="toggle('pre{{ frame.id }}', 'post{{ frame.id }}')"><pre>{{ line }}</pre></li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ol>
|
</ol>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
@ -268,7 +267,7 @@
|
||||||
<tbody>
|
<tbody>
|
||||||
{% for var in frame.vars|dictsort:0 %}
|
{% for var in frame.vars|dictsort:0 %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ var.0|force_escape }}</td>
|
<td>{{ var.0 }}</td>
|
||||||
<td class="code"><pre>{{ var.1 }}</pre></td>
|
<td class="code"><pre>{{ var.1 }}</pre></td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
@ -279,7 +278,6 @@
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
{% endautoescape %}
|
|
||||||
<form action="http://dpaste.com/" name="pasteform" id="pasteform" method="post">
|
<form action="http://dpaste.com/" name="pasteform" id="pasteform" method="post">
|
||||||
{% if not is_email %}
|
{% if not is_email %}
|
||||||
<div id="pastebinTraceback" class="pastebin">
|
<div id="pastebinTraceback" class="pastebin">
|
||||||
|
@ -318,9 +316,9 @@ In template {{ template_info.name }}, error at line {{ template_info.line }}
|
||||||
|
|
||||||
Traceback:{% for frame in frames %}
|
Traceback:{% for frame in frames %}
|
||||||
{% ifchanged frame.exc_cause %}{% if frame.exc_cause %}{% if frame.exc_cause_explicit %}
|
{% ifchanged frame.exc_cause %}{% if frame.exc_cause %}{% if frame.exc_cause_explicit %}
|
||||||
The above exception ({{ frame.exc_cause }}) was the direct cause of the following exception:
|
The above exception ({{ frame.exc_cause|force_escape }}) was the direct cause of the following exception:
|
||||||
{% else %}
|
{% else %}
|
||||||
During handling of the above exception ({{ frame.exc_cause }}), another exception occurred:
|
During handling of the above exception ({{ frame.exc_cause|force_escape }}), another exception occurred:
|
||||||
{% endif %}{% endif %}{% endifchanged %}
|
{% endif %}{% endif %}{% endifchanged %}
|
||||||
File "{{ frame.filename }}" in {{ frame.function }}
|
File "{{ frame.filename }}" in {{ frame.function }}
|
||||||
{% if frame.context_line %} {{ frame.lineno }}. {{ frame.context_line }}{% endif %}{% endfor %}
|
{% if frame.context_line %} {{ frame.lineno }}. {{ frame.context_line }}{% endif %}{% endfor %}
|
||||||
|
|
|
@ -5,3 +5,12 @@ Django 1.10.8 release notes
|
||||||
*September 5, 2017*
|
*September 5, 2017*
|
||||||
|
|
||||||
Django 1.10.8 fixes a security issue in 1.10.7.
|
Django 1.10.8 fixes a security issue in 1.10.7.
|
||||||
|
|
||||||
|
CVE-2017-12794: Possible XSS in traceback section of technical 500 debug page
|
||||||
|
=============================================================================
|
||||||
|
|
||||||
|
In older versions, HTML autoescaping was disabled in a portion of the template
|
||||||
|
for the technical 500 debug page. Given the right circumstances, this allowed
|
||||||
|
a cross-site scripting attack. This vulnerability shouldn't affect most
|
||||||
|
production sites since you shouldn't run with ``DEBUG = True`` (which makes
|
||||||
|
this page accessible) in your production settings.
|
||||||
|
|
|
@ -6,6 +6,15 @@ Django 1.11.5 release notes
|
||||||
|
|
||||||
Django 1.11.5 fixes a security issue and several bugs in 1.11.4.
|
Django 1.11.5 fixes a security issue and several bugs in 1.11.4.
|
||||||
|
|
||||||
|
CVE-2017-12794: Possible XSS in traceback section of technical 500 debug page
|
||||||
|
=============================================================================
|
||||||
|
|
||||||
|
In older versions, HTML autoescaping was disabled in a portion of the template
|
||||||
|
for the technical 500 debug page. Given the right circumstances, this allowed
|
||||||
|
a cross-site scripting attack. This vulnerability shouldn't affect most
|
||||||
|
production sites since you shouldn't run with ``DEBUG = True`` (which makes
|
||||||
|
this page accessible) in your production settings.
|
||||||
|
|
||||||
Bugfixes
|
Bugfixes
|
||||||
========
|
========
|
||||||
|
|
||||||
|
|
|
@ -349,10 +349,10 @@ class ExceptionReporterTests(SimpleTestCase):
|
||||||
request = self.rf.get('/test_view/')
|
request = self.rf.get('/test_view/')
|
||||||
try:
|
try:
|
||||||
try:
|
try:
|
||||||
raise AttributeError('Top level')
|
raise AttributeError(mark_safe('<p>Top level</p>'))
|
||||||
except AttributeError as explicit:
|
except AttributeError as explicit:
|
||||||
try:
|
try:
|
||||||
raise ValueError('Second exception') from explicit
|
raise ValueError(mark_safe('<p>Second exception</p>')) from explicit
|
||||||
except ValueError:
|
except ValueError:
|
||||||
raise IndexError(mark_safe('<p>Final exception</p>'))
|
raise IndexError(mark_safe('<p>Final exception</p>'))
|
||||||
except Exception:
|
except Exception:
|
||||||
|
@ -366,13 +366,13 @@ class ExceptionReporterTests(SimpleTestCase):
|
||||||
html = reporter.get_traceback_html()
|
html = reporter.get_traceback_html()
|
||||||
# Both messages are twice on page -- one rendered as html,
|
# Both messages are twice on page -- one rendered as html,
|
||||||
# one as plain text (for pastebin)
|
# one as plain text (for pastebin)
|
||||||
self.assertEqual(2, html.count(explicit_exc.format("Top level")))
|
self.assertEqual(2, html.count(explicit_exc.format('<p>Top level</p>')))
|
||||||
self.assertEqual(2, html.count(implicit_exc.format("Second exception")))
|
self.assertEqual(2, html.count(implicit_exc.format('<p>Second exception</p>')))
|
||||||
self.assertEqual(10, html.count('<p>Final exception</p>'))
|
self.assertEqual(10, html.count('<p>Final exception</p>'))
|
||||||
|
|
||||||
text = reporter.get_traceback_text()
|
text = reporter.get_traceback_text()
|
||||||
self.assertIn(explicit_exc.format("Top level"), text)
|
self.assertIn(explicit_exc.format('<p>Top level</p>'), text)
|
||||||
self.assertIn(implicit_exc.format("Second exception"), text)
|
self.assertIn(implicit_exc.format('<p>Second exception</p>'), text)
|
||||||
self.assertEqual(3, text.count('<p>Final exception</p>'))
|
self.assertEqual(3, text.count('<p>Final exception</p>'))
|
||||||
|
|
||||||
def test_reporting_frames_without_source(self):
|
def test_reporting_frames_without_source(self):
|
||||||
|
|
Loading…
Reference in New Issue