Fixed CVE-2023-41164 -- Fixed potential DoS in django.utils.encoding.uri_to_iri().

Thanks MProgrammer (https://hackerone.com/mprogrammer) for the report.

Co-authored-by: nessita <124304+nessita@users.noreply.github.com>
This commit is contained in:
Mariusz Felisiak 2023-08-22 08:53:03 +02:00
parent 048d75aeb1
commit 3f41d6d629
5 changed files with 43 additions and 5 deletions

View File

@ -220,6 +220,7 @@ def repercent_broken_unicode(path):
repercent-encode any octet produced that is not part of a strictly legal repercent-encode any octet produced that is not part of a strictly legal
UTF-8 octet sequence. UTF-8 octet sequence.
""" """
changed_parts = []
while True: while True:
try: try:
path.decode() path.decode()
@ -227,9 +228,10 @@ def repercent_broken_unicode(path):
# CVE-2019-14235: A recursion shouldn't be used since the exception # CVE-2019-14235: A recursion shouldn't be used since the exception
# handling uses massive amounts of memory # handling uses massive amounts of memory
repercent = quote(path[e.start : e.end], safe=b"/#%[]=:;$&()+,!?*@'~") repercent = quote(path[e.start : e.end], safe=b"/#%[]=:;$&()+,!?*@'~")
path = path[: e.start] + repercent.encode() + path[e.end :] changed_parts.append(path[: e.start] + repercent.encode())
path = path[e.end :]
else: else:
return path return b"".join(changed_parts) + path
def filepath_to_uri(path): def filepath_to_uri(path):

View File

@ -6,4 +6,9 @@ Django 3.2.21 release notes
Django 3.2.21 fixes a security issue with severity "moderate" in 3.2.20. Django 3.2.21 fixes a security issue with severity "moderate" in 3.2.20.
... CVE-2023-41164: Potential denial of service vulnerability in ``django.utils.encoding.uri_to_iri()``
===================================================================================================
``django.utils.encoding.uri_to_iri()`` was subject to potential denial of
service attack via certain inputs with a very large number of Unicode
characters.

View File

@ -6,4 +6,9 @@ Django 4.1.11 release notes
Django 4.1.11 fixes a security issue with severity "moderate" in 4.1.10. Django 4.1.11 fixes a security issue with severity "moderate" in 4.1.10.
... CVE-2023-41164: Potential denial of service vulnerability in ``django.utils.encoding.uri_to_iri()``
===================================================================================================
``django.utils.encoding.uri_to_iri()`` was subject to potential denial of
service attack via certain inputs with a very large number of Unicode
characters.

View File

@ -7,6 +7,13 @@ Django 4.2.5 release notes
Django 4.2.5 fixes a security issue with severity "moderate" and several bugs Django 4.2.5 fixes a security issue with severity "moderate" and several bugs
in 4.2.4. in 4.2.4.
CVE-2023-41164: Potential denial of service vulnerability in ``django.utils.encoding.uri_to_iri()``
===================================================================================================
``django.utils.encoding.uri_to_iri()`` was subject to potential denial of
service attack via certain inputs with a very large number of Unicode
characters.
Bugfixes Bugfixes
======== ========

View File

@ -1,9 +1,10 @@
import datetime import datetime
import inspect
import sys import sys
import unittest import unittest
from pathlib import Path from pathlib import Path
from unittest import mock from unittest import mock
from urllib.parse import quote_plus from urllib.parse import quote, quote_plus
from django.test import SimpleTestCase from django.test import SimpleTestCase
from django.utils.encoding import ( from django.utils.encoding import (
@ -120,6 +121,24 @@ class TestEncodingUtils(SimpleTestCase):
except RecursionError: except RecursionError:
self.fail("Unexpected RecursionError raised.") self.fail("Unexpected RecursionError raised.")
def test_repercent_broken_unicode_small_fragments(self):
data = b"test\xfctest\xfctest\xfc"
decoded_paths = []
def mock_quote(*args, **kwargs):
# The second frame is the call to repercent_broken_unicode().
decoded_paths.append(inspect.currentframe().f_back.f_locals["path"])
return quote(*args, **kwargs)
with mock.patch("django.utils.encoding.quote", mock_quote):
self.assertEqual(repercent_broken_unicode(data), b"test%FCtest%FCtest%FC")
# decode() is called on smaller fragment of the path each time.
self.assertEqual(
decoded_paths,
[b"test\xfctest\xfctest\xfc", b"test\xfctest\xfc", b"test\xfc"],
)
class TestRFC3987IEncodingUtils(unittest.TestCase): class TestRFC3987IEncodingUtils(unittest.TestCase):
def test_filepath_to_uri(self): def test_filepath_to_uri(self):