[2.2.x] Fixed CVE-2022-22818 -- Fixed possible XSS via {% debug %} template tag.

Thanks Keryn Knight for the report.

Backport of 394517f078 from main.

Co-authored-by: Adam Johnson <me@adamj.eu>
This commit is contained in:
Markus Holtermann 2022-01-02 00:37:40 +01:00 committed by Mariusz Felisiak
parent 4cafd3aacb
commit c27a7eb9f4
5 changed files with 68 additions and 15 deletions

View File

@ -8,7 +8,7 @@ from itertools import cycle as itertools_cycle, groupby
from django.conf import settings
from django.utils import timezone
from django.utils.html import conditional_escape, format_html
from django.utils.html import conditional_escape, escape, format_html
from django.utils.lorem_ipsum import paragraphs, words
from django.utils.safestring import mark_safe
@ -94,10 +94,13 @@ class CycleNode(Node):
class DebugNode(Node):
def render(self, context):
if not settings.DEBUG:
return ''
from pprint import pformat
output = [pformat(val) for val in context]
output = [escape(pformat(val)) for val in context]
output.append('\n\n')
output.append(pformat(sys.modules))
output.append(escape(pformat(sys.modules)))
return ''.join(output)

View File

@ -194,7 +194,13 @@ from its first value when it's next encountered.
---------
Outputs a whole load of debugging information, including the current context
and imported modules.
and imported modules. ``{% debug %}`` outputs nothing when the :setting:`DEBUG`
setting is ``False``.
.. versionchanged:: 2.2.27
In older versions, debugging information was displayed when the
:setting:`DEBUG` setting was ``False``.
.. templatetag:: extends

View File

@ -6,4 +6,12 @@ Django 2.2.27 release notes
Django 2.2.27 fixes two security issues with severity "medium" in 2.2.26.
...
CVE-2022-22818: Possible XSS via ``{% debug %}`` template tag
=============================================================
The ``{% debug %}`` template tag didn't properly encode the current context,
posing an XSS attack vector.
In order to avoid this vulnerability, ``{% debug %}`` no longer outputs an
information when the ``DEBUG`` setting is ``False``, and it ensures all context
variables are correctly escaped when the ``DEBUG`` setting is ``True``.

View File

@ -0,0 +1,46 @@
from django.contrib.auth.models import Group
from django.test import SimpleTestCase, override_settings
from ..utils import setup
@override_settings(DEBUG=True)
class DebugTests(SimpleTestCase):
@override_settings(DEBUG=False)
@setup({'non_debug': '{% debug %}'})
def test_non_debug(self):
output = self.engine.render_to_string('non_debug', {})
self.assertEqual(output, '')
@setup({'modules': '{% debug %}'})
def test_modules(self):
output = self.engine.render_to_string('modules', {})
self.assertIn(
'&#39;django&#39;: &lt;module &#39;django&#39; ',
output,
)
@setup({'plain': '{% debug %}'})
def test_plain(self):
output = self.engine.render_to_string('plain', {'a': 1})
self.assertTrue(output.startswith(
'{&#39;a&#39;: 1}'
'{&#39;False&#39;: False, &#39;None&#39;: None, '
'&#39;True&#39;: True}\n\n{'
))
@setup({'non_ascii': '{% debug %}'})
def test_non_ascii(self):
group = Group(name="清風")
output = self.engine.render_to_string('non_ascii', {'group': group})
self.assertTrue(output.startswith(
'{&#39;group&#39;: &lt;Group: 清風&gt;}'
))
@setup({'script': '{% debug %}'})
def test_script(self):
output = self.engine.render_to_string('script', {'frag': '<script>'})
self.assertTrue(output.startswith(
'{&#39;frag&#39;: &#39;&lt;script&gt;&#39;}'
))

View File

@ -1,6 +1,5 @@
import sys
from django.contrib.auth.models import Group
from django.template import Context, Engine, TemplateSyntaxError
from django.template.base import UNKNOWN_SOURCE
from django.test import SimpleTestCase, override_settings
@ -143,15 +142,6 @@ class TemplateTests(SimpleTestCase):
with self.assertRaises(NoReverseMatch):
t.render(Context())
def test_debug_tag_non_ascii(self):
"""
#23060 -- Test non-ASCII model representation in debug output.
"""
group = Group(name="清風")
c1 = Context({"objs": [group]})
t1 = Engine().from_string('{% debug %}')
self.assertIn("清風", t1.render(c1))
def test_extends_generic_template(self):
"""
#24338 -- Allow extending django.template.backends.django.Template