[3.1.x] Fixed #30530, CVE-2021-44420 -- Fixed potential bypass of an upstream access control based on URL paths.

Thanks Sjoerd Job Postmus and TengMA(@te3t123) for reports.

Backport of d4dcd5b9dd from main.
This commit is contained in:
Florian Apolloner 2021-11-29 11:52:03 +01:00 committed by Mariusz Felisiak
parent cfb780dafe
commit 22bd174881
4 changed files with 29 additions and 4 deletions

View File

@ -153,7 +153,11 @@ class RegexPattern(CheckURLMixin):
self.converters = {}
def match(self, path):
match = self.regex.search(path)
match = (
self.regex.fullmatch(path)
if self._is_endpoint and self.regex.pattern.endswith('$')
else self.regex.search(path)
)
if match:
# If there are any named groups, use those as kwargs, ignoring
# non-named groups. Otherwise, pass all non-named arguments as
@ -240,7 +244,7 @@ def _route_to_regex(route, is_endpoint=False):
converters[parameter] = converter
parts.append('(?P<' + parameter + '>' + converter.regex + ')')
if is_endpoint:
parts.append('$')
parts.append(r'\Z')
return ''.join(parts), converters

View File

@ -6,4 +6,8 @@ Django 2.2.25 release notes
Django 2.2.25 fixes a security issue with severity "low" in 2.2.24.
...
CVE-2021-44420: Potential bypass of an upstream access control based on URL paths
=================================================================================
HTTP requests for URLs with trailing newlines could bypass an upstream access
control based on URL paths.

View File

@ -6,4 +6,8 @@ Django 3.1.14 release notes
Django 3.1.14 fixes a security issue with severity "low" in 3.1.13.
...
CVE-2021-44420: Potential bypass of an upstream access control based on URL paths
=================================================================================
HTTP requests for URLs with trailing newlines could bypass an upstream access
control based on URL paths.

View File

@ -147,6 +147,19 @@ class SimplifiedURLTests(SimpleTestCase):
with self.assertRaisesMessage(ImproperlyConfigured, msg):
path('space/<int: num>', empty_view)
def test_path_trailing_newlines(self):
tests = [
'/articles/2003/\n',
'/articles/2010/\n',
'/en/foo/\n',
'/included_urls/extra/\n',
'/regex/1/\n',
'/users/1/\n',
]
for url in tests:
with self.subTest(url=url), self.assertRaises(Resolver404):
resolve(url)
@override_settings(ROOT_URLCONF='urlpatterns.converter_urls')
class ConverterTests(SimpleTestCase):