From c1171ffbd570db90ca206c30f8e2b9f691243820 Mon Sep 17 00:00:00 2001 From: Adam Johnson Date: Mon, 22 Jan 2024 13:21:13 +0000 Subject: [PATCH] [3.2.x] Fixed CVE-2024-24680 -- Mitigated potential DoS in intcomma template filter. Thanks Seokchan Yoon for the report. Co-authored-by: Mariusz Felisiak Co-authored-by: Natalia <124304+nessita@users.noreply.github.com> Co-authored-by: Shai Berger --- .../contrib/humanize/templatetags/humanize.py | 13 +- docs/releases/3.2.24.txt | 6 +- tests/humanize_tests/tests.py | 140 ++++++++++++++++-- 3 files changed, 140 insertions(+), 19 deletions(-) diff --git a/django/contrib/humanize/templatetags/humanize.py b/django/contrib/humanize/templatetags/humanize.py index 753a0d9fe1..238aaf2253 100644 --- a/django/contrib/humanize/templatetags/humanize.py +++ b/django/contrib/humanize/templatetags/humanize.py @@ -70,12 +70,13 @@ def intcomma(value, use_l10n=True): return intcomma(value, False) else: return number_format(value, use_l10n=True, force_grouping=True) - orig = str(value) - new = re.sub(r"^(-?\d+)(\d{3})", r'\g<1>,\g<2>', orig) - if orig == new: - return new - else: - return intcomma(new, use_l10n) + result = str(value) + match = re.match(r"-?\d+", result) + if match: + prefix = match[0] + prefix_with_commas = re.sub(r"\d{3}", r"\g<0>,", prefix[::-1])[::-1] + result = prefix_with_commas + result[len(prefix) :] + return result # A tuple of standard large number to their converters diff --git a/docs/releases/3.2.24.txt b/docs/releases/3.2.24.txt index 1ab7024f73..67be0f65d1 100644 --- a/docs/releases/3.2.24.txt +++ b/docs/releases/3.2.24.txt @@ -6,4 +6,8 @@ Django 3.2.24 release notes Django 3.2.24 fixes a security issue with severity "moderate" in 3.2.23. -... +CVE-2024-24680: Potential denial-of-service in ``intcomma`` template filter +=========================================================================== + +The ``intcomma`` template filter was subject to a potential denial-of-service +attack when used with very long strings. diff --git a/tests/humanize_tests/tests.py b/tests/humanize_tests/tests.py index a0d16bbfed..3c227873cf 100644 --- a/tests/humanize_tests/tests.py +++ b/tests/humanize_tests/tests.py @@ -66,28 +66,144 @@ class HumanizeTests(SimpleTestCase): def test_intcomma(self): test_list = ( - 100, 1000, 10123, 10311, 1000000, 1234567.25, '100', '1000', - '10123', '10311', '1000000', '1234567.1234567', - Decimal('1234567.1234567'), None, + 100, + -100, + 1000, + -1000, + 10123, + -10123, + 10311, + -10311, + 1000000, + -1000000, + 1234567.25, + -1234567.25, + "100", + "-100", + "1000", + "-1000", + "10123", + "-10123", + "10311", + "-10311", + "1000000", + "-1000000", + "1234567.1234567", + "-1234567.1234567", + Decimal("1234567.1234567"), + Decimal("-1234567.1234567"), + None, + "1234567", + "-1234567", + "1234567.12", + "-1234567.12", + "the quick brown fox jumped over the lazy dog", ) result_list = ( - '100', '1,000', '10,123', '10,311', '1,000,000', '1,234,567.25', - '100', '1,000', '10,123', '10,311', '1,000,000', '1,234,567.1234567', - '1,234,567.1234567', None, + "100", + "-100", + "1,000", + "-1,000", + "10,123", + "-10,123", + "10,311", + "-10,311", + "1,000,000", + "-1,000,000", + "1,234,567.25", + "-1,234,567.25", + "100", + "-100", + "1,000", + "-1,000", + "10,123", + "-10,123", + "10,311", + "-10,311", + "1,000,000", + "-1,000,000", + "1,234,567.1234567", + "-1,234,567.1234567", + "1,234,567.1234567", + "-1,234,567.1234567", + None, + "1,234,567", + "-1,234,567", + "1,234,567.12", + "-1,234,567.12", + "the quick brown fox jumped over the lazy dog", ) with translation.override('en'): self.humanize_tester(test_list, result_list, 'intcomma') def test_l10n_intcomma(self): test_list = ( - 100, 1000, 10123, 10311, 1000000, 1234567.25, '100', '1000', - '10123', '10311', '1000000', '1234567.1234567', - Decimal('1234567.1234567'), None, + 100, + -100, + 1000, + -1000, + 10123, + -10123, + 10311, + -10311, + 1000000, + -1000000, + 1234567.25, + -1234567.25, + "100", + "-100", + "1000", + "-1000", + "10123", + "-10123", + "10311", + "-10311", + "1000000", + "-1000000", + "1234567.1234567", + "-1234567.1234567", + Decimal("1234567.1234567"), + -Decimal("1234567.1234567"), + None, + "1234567", + "-1234567", + "1234567.12", + "-1234567.12", + "the quick brown fox jumped over the lazy dog", ) result_list = ( - '100', '1,000', '10,123', '10,311', '1,000,000', '1,234,567.25', - '100', '1,000', '10,123', '10,311', '1,000,000', '1,234,567.1234567', - '1,234,567.1234567', None, + "100", + "-100", + "1,000", + "-1,000", + "10,123", + "-10,123", + "10,311", + "-10,311", + "1,000,000", + "-1,000,000", + "1,234,567.25", + "-1,234,567.25", + "100", + "-100", + "1,000", + "-1,000", + "10,123", + "-10,123", + "10,311", + "-10,311", + "1,000,000", + "-1,000,000", + "1,234,567.1234567", + "-1,234,567.1234567", + "1,234,567.1234567", + "-1,234,567.1234567", + None, + "1,234,567", + "-1,234,567", + "1,234,567.12", + "-1,234,567.12", + "the quick brown fox jumped over the lazy dog", ) with self.settings(USE_L10N=True, USE_THOUSAND_SEPARATOR=False): with translation.override('en'):