[2.2.x] Fixed CVE-2019-14235 -- Fixed potential memory exhaustion in django.utils.encoding.uri_to_iri().

Thanks to Guido Vranken for initial report.
This commit is contained in:
Florian Apolloner 2019-07-19 17:04:53 +02:00 committed by Carlton Gibson
parent 4f5b58f5cd
commit cf694e6852
5 changed files with 52 additions and 9 deletions

View File

@ -225,13 +225,16 @@ 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.
""" """
try: while True:
path.decode() try:
except UnicodeDecodeError as e: path.decode()
repercent = quote(path[e.start:e.end], safe=b"/#%[]=:;$&()+,!?*@'~") except UnicodeDecodeError as e:
path = repercent_broken_unicode( # CVE-2019-14235: A recursion shouldn't be used since the exception
path[:e.start] + force_bytes(repercent) + path[e.end:]) # handling uses massive amounts of memory
return path repercent = quote(path[e.start:e.end], safe=b"/#%[]=:;$&()+,!?*@'~")
path = path[:e.start] + force_bytes(repercent) + path[e.end:]
else:
return path
def filepath_to_uri(path): def filepath_to_uri(path):

View File

@ -45,3 +45,13 @@ CVE-2019-14234: SQL injection possibility in key and index lookups for ``JSONFie
<hstorefield.key>` for :class:`~django.contrib.postgres.fields.HStoreField` <hstorefield.key>` for :class:`~django.contrib.postgres.fields.HStoreField`
were subject to SQL injection, using a suitably crafted dictionary, with were subject to SQL injection, using a suitably crafted dictionary, with
dictionary expansion, as the ``**kwargs`` passed to ``QuerySet.filter()``. dictionary expansion, as the ``**kwargs`` passed to ``QuerySet.filter()``.
CVE-2019-14235: Potential memory exhaustion in ``django.utils.encoding.uri_to_iri()``
=====================================================================================
If passed certain inputs, :func:`django.utils.encoding.uri_to_iri` could lead
to significant memory usage due to excessive recursion when re-percent-encoding
invalid UTF-8 octet sequences.
``uri_to_iri()`` now avoids recursion when re-percent-encoding invalid UTF-8
octet sequences.

View File

@ -45,3 +45,13 @@ CVE-2019-14234: SQL injection possibility in key and index lookups for ``JSONFie
<hstorefield.key>` for :class:`~django.contrib.postgres.fields.HStoreField` <hstorefield.key>` for :class:`~django.contrib.postgres.fields.HStoreField`
were subject to SQL injection, using a suitably crafted dictionary, with were subject to SQL injection, using a suitably crafted dictionary, with
dictionary expansion, as the ``**kwargs`` passed to ``QuerySet.filter()``. dictionary expansion, as the ``**kwargs`` passed to ``QuerySet.filter()``.
CVE-2019-14235: Potential memory exhaustion in ``django.utils.encoding.uri_to_iri()``
=====================================================================================
If passed certain inputs, :func:`django.utils.encoding.uri_to_iri` could lead
to significant memory usage due to excessive recursion when re-percent-encoding
invalid UTF-8 octet sequences.
``uri_to_iri()`` now avoids recursion when re-percent-encoding invalid UTF-8
octet sequences.

View File

@ -46,6 +46,16 @@ CVE-2019-14234: SQL injection possibility in key and index lookups for ``JSONFie
were subject to SQL injection, using a suitably crafted dictionary, with were subject to SQL injection, using a suitably crafted dictionary, with
dictionary expansion, as the ``**kwargs`` passed to ``QuerySet.filter()``. dictionary expansion, as the ``**kwargs`` passed to ``QuerySet.filter()``.
CVE-2019-14235: Potential memory exhaustion in ``django.utils.encoding.uri_to_iri()``
=====================================================================================
If passed certain inputs, :func:`django.utils.encoding.uri_to_iri` could lead
to significant memory usage due to excessive recursion when re-percent-encoding
invalid UTF-8 octet sequences.
``uri_to_iri()`` now avoids recursion when re-percent-encoding invalid UTF-8
octet sequences.
Bugfixes Bugfixes
======== ========

View File

@ -1,4 +1,5 @@
import datetime import datetime
import sys
import unittest import unittest
from unittest import mock from unittest import mock
from urllib.parse import quote_plus from urllib.parse import quote_plus
@ -6,8 +7,8 @@ from urllib.parse import quote_plus
from django.test import SimpleTestCase from django.test import SimpleTestCase
from django.utils.encoding import ( from django.utils.encoding import (
DjangoUnicodeDecodeError, escape_uri_path, filepath_to_uri, force_bytes, DjangoUnicodeDecodeError, escape_uri_path, filepath_to_uri, force_bytes,
force_text, get_system_encoding, iri_to_uri, smart_bytes, smart_text, force_text, get_system_encoding, iri_to_uri, repercent_broken_unicode,
uri_to_iri, smart_bytes, smart_text, uri_to_iri,
) )
from django.utils.functional import SimpleLazyObject from django.utils.functional import SimpleLazyObject
from django.utils.translation import gettext_lazy from django.utils.translation import gettext_lazy
@ -90,6 +91,15 @@ class TestEncodingUtils(SimpleTestCase):
with mock.patch('locale.getdefaultlocale', side_effect=Exception): with mock.patch('locale.getdefaultlocale', side_effect=Exception):
self.assertEqual(get_system_encoding(), 'ascii') self.assertEqual(get_system_encoding(), 'ascii')
def test_repercent_broken_unicode_recursion_error(self):
# Prepare a string long enough to force a recursion error if the tested
# function uses recursion.
data = b'\xfc' * sys.getrecursionlimit()
try:
self.assertEqual(repercent_broken_unicode(data), b'%FC' * sys.getrecursionlimit())
except RecursionError:
self.fail('Unexpected RecursionError raised.')
class TestRFC3987IEncodingUtils(unittest.TestCase): class TestRFC3987IEncodingUtils(unittest.TestCase):