From 367869214e0744b16729bc3c725126263889c1a7 Mon Sep 17 00:00:00 2001
From: wk333 <13474090681@163.com>
Date: Mon, 9 Dec 2024 10:11:48 +0800
Subject: [PATCH] Fix CVE-2024-53907 CVE-2024-53908
---
CVE-2024-53907.patch | 88 ++++++++++++++++++++++++++
CVE-2024-53908.patch | 145 +++++++++++++++++++++++++++++++++++++++++++
python-django.spec | 7 ++-
3 files changed, 239 insertions(+), 1 deletion(-)
create mode 100644 CVE-2024-53907.patch
create mode 100644 CVE-2024-53908.patch
diff --git a/CVE-2024-53907.patch b/CVE-2024-53907.patch
new file mode 100644
index 0000000..22570ab
--- /dev/null
+++ b/CVE-2024-53907.patch
@@ -0,0 +1,88 @@
+From bbc74a7f7eb7335e913bdb4787f22e83a9be947e Mon Sep 17 00:00:00 2001
+From: Sarah Boyce <42296566+sarahboyce@users.noreply.github.com>
+Date: Wed, 13 Nov 2024 15:06:23 +0100
+Subject: [PATCH] [5.1.x] Fixed CVE-2024-53907 -- Mitigated potential DoS in
+ strip_tags().
+
+Origin: https://github.com/django/django/commit/bbc74a7f7eb7335e913bdb4787f22e83a9be947e
+
+Thanks to jiangniao for the report, and Shai Berger and Natalia Bidart
+for the reviews.
+---
+ django/utils/html.py | 10 ++++++++--
+ tests/utils_tests/test_html.py | 7 +++++++
+ 5 files changed, 63 insertions(+), 2 deletions(-)
+
+diff --git a/django/utils/html.py b/django/utils/html.py
+index d9513fc75848..ff8684f5a974 100644
+--- a/django/utils/html.py
++++ b/django/utils/html.py
+@@ -7,6 +7,7 @@
+ from html.parser import HTMLParser
+ from urllib.parse import parse_qsl, quote, unquote, urlencode, urlsplit, urlunsplit
+
++from django.core.exceptions import SuspiciousOperation
+ from django.utils.deprecation import RemovedInDjango60Warning
+ from django.utils.encoding import punycode
+ from django.utils.functional import Promise, cached_property, keep_lazy, keep_lazy_text
+@@ -39,6 +40,7 @@
+ )
+
+ MAX_URL_LENGTH = 2048
++MAX_STRIP_TAGS_DEPTH = 50
+
+
+ @keep_lazy(SafeString)
+@@ -205,15 +207,19 @@ def _strip_once(value):
+ @keep_lazy_text
+ def strip_tags(value):
+ """Return the given HTML with all tags stripped."""
+- # Note: in typical case this loop executes _strip_once once. Loop condition
+- # is redundant, but helps to reduce number of executions of _strip_once.
+ value = str(value)
++ # Note: in typical case this loop executes _strip_once twice (the second
++ # execution does not remove any more tags).
++ strip_tags_depth = 0
+ while "<" in value and ">" in value:
++ if strip_tags_depth >= MAX_STRIP_TAGS_DEPTH:
++ raise SuspiciousOperation
+ new_value = _strip_once(value)
+ if value.count("<") == new_value.count("<"):
+ # _strip_once wasn't able to detect more tags.
+ break
+ value = new_value
++ strip_tags_depth += 1
+ return value
+
+
+diff --git a/tests/utils_tests/test_html.py b/tests/utils_tests/test_html.py
+index 9bee483dc7ff..75873061de41 100644
+--- a/tests/utils_tests/test_html.py
++++ b/tests/utils_tests/test_html.py
+@@ -1,6 +1,7 @@
+ import os
+ from datetime import datetime
+
++from django.core.exceptions import SuspiciousOperation
+ from django.core.serializers.json import DjangoJSONEncoder
+ from django.test import SimpleTestCase
+ from django.utils.deprecation import RemovedInDjango60Warning
+@@ -124,12 +125,18 @@ def test_strip_tags(self):
+ ("&h", "alert()h"),
+ (">br>br>br>X", "XX"),
++ ("<" * 50 + "a>" * 50, ""),
+ )
+ for value, output in items:
+ with self.subTest(value=value, output=output):
+ self.check_output(strip_tags, value, output)
+ self.check_output(strip_tags, lazystr(value), output)
+
++ def test_strip_tags_suspicious_operation(self):
++ value = "<" * 51 + "a>" * 51, ""
++ with self.assertRaises(SuspiciousOperation):
++ strip_tags(value)
++
+ def test_strip_tags_files(self):
+ # Test with more lengthy content (also catching performance regressions)
+ for filename in ("strip_tags1.html", "strip_tags2.txt"):
diff --git a/CVE-2024-53908.patch b/CVE-2024-53908.patch
new file mode 100644
index 0000000..684df2a
--- /dev/null
+++ b/CVE-2024-53908.patch
@@ -0,0 +1,145 @@
+From 6943d61818e63e77b65d8b1ae65941e8f04bd87b Mon Sep 17 00:00:00 2001
+From: Simon Charette
+Date: Fri, 8 Nov 2024 21:27:31 -0500
+Subject: [PATCH] [5.1.x] Fixed CVE-2024-53908 -- Prevented SQL injections in
+ direct HasKeyLookup usage on Oracle.
+
+Origin: https://github.com/django/django/commit/6943d61818e63e77b65d8b1ae65941e8f04bd87b
+
+Thanks Seokchan Yoon for the report, and Mariusz Felisiak and Sarah
+Boyce for the reviews.
+---
+ django/db/models/fields/json.py | 53 ++++++++++++++++++----------
+ tests/model_fields/test_jsonfield.py | 9 +++++
+ 5 files changed, 71 insertions(+), 18 deletions(-)
+
+diff --git a/django/db/models/fields/json.py b/django/db/models/fields/json.py
+index 1b219e620c9a..608da6036f87 100644
+--- a/django/db/models/fields/json.py
++++ b/django/db/models/fields/json.py
+@@ -193,20 +193,18 @@ def compile_json_path_final_key(self, key_transform):
+ # Compile the final key without interpreting ints as array elements.
+ return ".%s" % json.dumps(key_transform)
+
+- def as_sql(self, compiler, connection, template=None):
++ def _as_sql_parts(self, compiler, connection):
+ # Process JSON path from the left-hand side.
+ if isinstance(self.lhs, KeyTransform):
+- lhs, lhs_params, lhs_key_transforms = self.lhs.preprocess_lhs(
++ lhs_sql, lhs_params, lhs_key_transforms = self.lhs.preprocess_lhs(
+ compiler, connection
+ )
+ lhs_json_path = compile_json_path(lhs_key_transforms)
+ else:
+- lhs, lhs_params = self.process_lhs(compiler, connection)
++ lhs_sql, lhs_params = self.process_lhs(compiler, connection)
+ lhs_json_path = "$"
+- sql = template % lhs
+ # Process JSON path from the right-hand side.
+ rhs = self.rhs
+- rhs_params = []
+ if not isinstance(rhs, (list, tuple)):
+ rhs = [rhs]
+ for key in rhs:
+@@ -217,24 +215,43 @@ def as_sql(self, compiler, connection, template=None):
+ *rhs_key_transforms, final_key = rhs_key_transforms
+ rhs_json_path = compile_json_path(rhs_key_transforms, include_root=False)
+ rhs_json_path += self.compile_json_path_final_key(final_key)
+- rhs_params.append(lhs_json_path + rhs_json_path)
++ yield lhs_sql, lhs_params, lhs_json_path + rhs_json_path
++
++ def _combine_sql_parts(self, parts):
+ # Add condition for each key.
+ if self.logical_operator:
+- sql = "(%s)" % self.logical_operator.join([sql] * len(rhs_params))
+- return sql, tuple(lhs_params) + tuple(rhs_params)
++ return "(%s)" % self.logical_operator.join(parts)
++ return "".join(parts)
++
++ def as_sql(self, compiler, connection, template=None):
++ sql_parts = []
++ params = []
++ for lhs_sql, lhs_params, rhs_json_path in self._as_sql_parts(
++ compiler, connection
++ ):
++ sql_parts.append(template % (lhs_sql, "%s"))
++ params.extend(lhs_params + [rhs_json_path])
++ return self._combine_sql_parts(sql_parts), tuple(params)
+
+ def as_mysql(self, compiler, connection):
+ return self.as_sql(
+- compiler, connection, template="JSON_CONTAINS_PATH(%s, 'one', %%s)"
++ compiler, connection, template="JSON_CONTAINS_PATH(%s, 'one', %s)"
+ )
+
+ def as_oracle(self, compiler, connection):
+- sql, params = self.as_sql(
+- compiler, connection, template="JSON_EXISTS(%s, '%%s')"
+- )
+- # Add paths directly into SQL because path expressions cannot be passed
+- # as bind variables on Oracle.
+- return sql % tuple(params), []
++ template = "JSON_EXISTS(%s, '%s')"
++ sql_parts = []
++ params = []
++ for lhs_sql, lhs_params, rhs_json_path in self._as_sql_parts(
++ compiler, connection
++ ):
++ # Add right-hand-side directly into SQL because it cannot be passed
++ # as bind variables to JSON_EXISTS. It might result in invalid
++ # queries but it is assumed that it cannot be evaded because the
++ # path is JSON serialized.
++ sql_parts.append(template % (lhs_sql, rhs_json_path))
++ params.extend(lhs_params)
++ return self._combine_sql_parts(sql_parts), tuple(params)
+
+ def as_postgresql(self, compiler, connection):
+ if isinstance(self.rhs, KeyTransform):
+@@ -246,7 +263,7 @@ def as_postgresql(self, compiler, connection):
+
+ def as_sqlite(self, compiler, connection):
+ return self.as_sql(
+- compiler, connection, template="JSON_TYPE(%s, %%s) IS NOT NULL"
++ compiler, connection, template="JSON_TYPE(%s, %s) IS NOT NULL"
+ )
+
+
+@@ -455,9 +472,9 @@ def as_oracle(self, compiler, connection):
+ return "(NOT %s OR %s IS NULL)" % (sql, lhs), tuple(params) + tuple(lhs_params)
+
+ def as_sqlite(self, compiler, connection):
+- template = "JSON_TYPE(%s, %%s) IS NULL"
++ template = "JSON_TYPE(%s, %s) IS NULL"
+ if not self.rhs:
+- template = "JSON_TYPE(%s, %%s) IS NOT NULL"
++ template = "JSON_TYPE(%s, %s) IS NOT NULL"
+ return HasKeyOrArrayIndex(self.lhs.lhs, self.lhs.key_name).as_sql(
+ compiler,
+ connection,
+diff --git a/tests/model_fields/test_jsonfield.py b/tests/model_fields/test_jsonfield.py
+index ff42b1a14c38..e517ef682675 100644
+--- a/tests/model_fields/test_jsonfield.py
++++ b/tests/model_fields/test_jsonfield.py
+@@ -29,6 +29,7 @@
+ from django.db.models.expressions import RawSQL
+ from django.db.models.fields.json import (
+ KT,
++ HasKey,
+ KeyTextTransform,
+ KeyTransform,
+ KeyTransformFactory,
+@@ -582,6 +583,14 @@ def test_has_key_deep(self):
+ [expected],
+ )
+
++ def test_has_key_literal_lookup(self):
++ self.assertSequenceEqual(
++ NullableJSONModel.objects.filter(
++ HasKey(Value({"foo": "bar"}, JSONField()), "foo")
++ ).order_by("id"),
++ self.objs,
++ )
++
+ def test_has_key_list(self):
+ obj = NullableJSONModel.objects.create(value=[{"a": 1}, {"b": "x"}])
+ tests = [
diff --git a/python-django.spec b/python-django.spec
index 5981b90..91f16e0 100644
--- a/python-django.spec
+++ b/python-django.spec
@@ -1,13 +1,15 @@
%global _empty_manifest_terminate_build 0
Name: python-django
Version: 5.1
-Release: 2
+Release: 3
Summary: A high-level Python Web framework that encourages rapid development and clean, pragmatic design.
License: Apache-2.0 and Python-2.0 and BSD-3-Clause
URL: https://www.djangoproject.com/
Source0: https://files.pythonhosted.org/packages/source/d/Django/Django-%{version}.tar.gz
Patch0: CVE-2024-45230.patch
Patch1: CVE-2024-45231.patch
+Patch2: CVE-2024-53907.patch
+Patch3: CVE-2024-53908.patch
BuildArch: noarch
%description
@@ -74,6 +76,9 @@ mv %{buildroot}/doclist.lst .
%{_docdir}/*
%changelog
+* Mon Dec 09 2024 wangkai <13474090681@163.com> - 5.1-3
+- Fix CVE-2024-53907 CVE-2024-53908
+
* Thu Oct 10 2024 zhangxianting - 5.1-2
- Fix CVE-2024-45230 CVE-2024-45231
--
Gitee