From 46c10bce575cf9d17ff90e5b3e797a4eaacd3337 Mon Sep 17 00:00:00 2001 From: starlet-dx <15929766099@163.com> Date: Tue, 5 Jul 2022 17:23:06 +0800 Subject: [PATCH] Fix CVE-2022-34265 --- CVE-2022-34265.patch | 109 +++++++++++++++++++++++++++++++++++++++++++ python-django.spec | 9 +++- 2 files changed, 116 insertions(+), 2 deletions(-) create mode 100644 CVE-2022-34265.patch diff --git a/CVE-2022-34265.patch b/CVE-2022-34265.patch new file mode 100644 index 0000000..3d4f452 --- /dev/null +++ b/CVE-2022-34265.patch @@ -0,0 +1,109 @@ +From a9010fe5555e6086a9d9ae50069579400ef0685e Mon Sep 17 00:00:00 2001 +From: Mariusz Felisiak +Date: Wed, 22 Jun 2022 12:44:04 +0200 +Subject: [PATCH] [3.2.x] Fixed CVE-2022-34265 -- Protected + Trunc(kind)/Extract(lookup_name) against SQL injection. + +Thanks Takuto Yoshikai (Aeye Security Lab) for the report. +--- + django/db/backends/base/operations.py | 3 ++ + django/db/models/functions/datetime.py | 4 +++ + docs/releases/3.2.14.txt | 11 ++++++ + .../datetime/test_extract_trunc.py | 34 +++++++++++++++++++ + 4 files changed, 52 insertions(+) + +diff --git a/django/db/backends/base/operations.py b/django/db/backends/base/operations.py +index 0fcc607bcfb0..cdcd9885ba27 100644 +--- a/django/db/backends/base/operations.py ++++ b/django/db/backends/base/operations.py +@@ -9,6 +9,7 @@ + from django.db.backends import utils + from django.utils import timezone + from django.utils.encoding import force_str ++from django.utils.regex_helper import _lazy_re_compile + + + class BaseDatabaseOperations: +@@ -53,6 +54,8 @@ class BaseDatabaseOperations: + # Prefix for EXPLAIN queries, or None EXPLAIN isn't supported. + explain_prefix = None + ++ extract_trunc_lookup_pattern = _lazy_re_compile(r"[\w\-_()]+") ++ + def __init__(self, connection): + self.connection = connection + self._cache = None +diff --git a/django/db/models/functions/datetime.py b/django/db/models/functions/datetime.py +index 90e6f41be057..47651d281f19 100644 +--- a/django/db/models/functions/datetime.py ++++ b/django/db/models/functions/datetime.py +@@ -41,6 +41,8 @@ def __init__(self, expression, lookup_name=None, tzinfo=None, **extra): + super().__init__(expression, **extra) + + def as_sql(self, compiler, connection): ++ if not connection.ops.extract_trunc_lookup_pattern.fullmatch(self.lookup_name): ++ raise ValueError("Invalid lookup_name: %s" % self.lookup_name) + sql, params = compiler.compile(self.lhs) + lhs_output_field = self.lhs.output_field + if isinstance(lhs_output_field, DateTimeField): +@@ -192,6 +194,8 @@ def __init__(self, expression, output_field=None, tzinfo=None, is_dst=None, **ex + super().__init__(expression, output_field=output_field, **extra) + + def as_sql(self, compiler, connection): ++ if not connection.ops.extract_trunc_lookup_pattern.fullmatch(self.kind): ++ raise ValueError("Invalid kind: %s" % self.kind) + inner_sql, inner_params = compiler.compile(self.lhs) + tzname = None + if isinstance(self.lhs.output_field, DateTimeField): +diff --git a/tests/db_functions/datetime/test_extract_trunc.py b/tests/db_functions/datetime/test_extract_trunc.py +index 258600127f93..27ed3ae63ee5 100644 +--- a/tests/db_functions/datetime/test_extract_trunc.py ++++ b/tests/db_functions/datetime/test_extract_trunc.py +@@ -177,6 +177,23 @@ def test_extract_year_lessthan_lookup(self): + self.assertEqual(qs.count(), 1) + self.assertGreaterEqual(str(qs.query).lower().count('extract'), 2) + ++ def test_extract_lookup_name_sql_injection(self): ++ start_datetime = datetime(2015, 6, 15, 14, 30, 50, 321) ++ end_datetime = datetime(2016, 6, 15, 14, 10, 50, 123) ++ if settings.USE_TZ: ++ start_datetime = timezone.make_aware(start_datetime) ++ end_datetime = timezone.make_aware(end_datetime) ++ self.create_model(start_datetime, end_datetime) ++ self.create_model(end_datetime, start_datetime) ++ ++ msg = "Invalid lookup_name: " ++ with self.assertRaisesMessage(ValueError, msg): ++ DTModel.objects.filter( ++ start_datetime__year=Extract( ++ "start_datetime", "day' FROM start_datetime)) OR 1=1;--" ++ ) ++ ).exists() ++ + def test_extract_func(self): + start_datetime = datetime(2015, 6, 15, 14, 30, 50, 321) + end_datetime = datetime(2016, 6, 15, 14, 10, 50, 123) +@@ -620,6 +637,23 @@ def test_extract_second_func(self): + ) + self.assertEqual(DTModel.objects.filter(start_datetime__second=ExtractSecond('start_datetime')).count(), 2) + ++ def test_trunc_lookup_name_sql_injection(self): ++ start_datetime = datetime(2015, 6, 15, 14, 30, 50, 321) ++ end_datetime = datetime(2016, 6, 15, 14, 10, 50, 123) ++ if settings.USE_TZ: ++ start_datetime = timezone.make_aware(start_datetime) ++ end_datetime = timezone.make_aware(end_datetime) ++ self.create_model(start_datetime, end_datetime) ++ self.create_model(end_datetime, start_datetime) ++ msg = "Invalid kind: " ++ with self.assertRaisesMessage(ValueError, msg): ++ DTModel.objects.filter( ++ start_datetime__date=Trunc( ++ "start_datetime", ++ "year', start_datetime)) OR 1=1;--", ++ ) ++ ).exists() ++ + def test_trunc_func(self): + start_datetime = datetime(2015, 6, 15, 14, 30, 50, 321) + end_datetime = datetime(2016, 6, 15, 14, 10, 50, 123) diff --git a/python-django.spec b/python-django.spec index d2d6697..9d56b23 100644 --- a/python-django.spec +++ b/python-django.spec @@ -1,11 +1,13 @@ %global _empty_manifest_terminate_build 0 Name: python-django Version: 3.2.12 -Release: 1 +Release: 2 Summary: A high-level Python Web framework that encourages rapid development and clean, pragmatic design. -License: Apache-2.0 and Python-2.0 and OFL-1.1 and MIT +License: Apache-2.0 and Python-2.0 and BSD-3-Clause URL: https://www.djangoproject.com/ Source0: https://github.com/django/django/archive/refs/tags/3.2.12.tar.gz +#https://github.com/django/django/commit/a9010fe5555e6086a9d9ae50069579400ef0685e +Patch0: CVE-2022-34265.patch BuildArch: noarch @@ -73,6 +75,9 @@ mv %{buildroot}/doclist.lst . %{_docdir}/* %changelog +* Tue Jul 05 2022 yaoxin - 3.2.12-2 +- Fix CVE-2022-34265 + * Wed May 18 2022 xigaoxinyan - 3.2.12-1 - Update to 3.2.12 -- Gitee