Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 0bd57a8

Browse files
charettesfelixxm
authored andcommitted
[3.1.x] Fixed CVE-2021-35042 -- Prevented SQL injection in QuerySet.order_by().
Regression introduced in 5139487 by marking the raw SQL column reference feature for deprecation in Django 4.0 while lifting the column format validation. In retrospective the validation should have been kept around and the user should have been pointed at using RawSQL expressions during the deprecation period. The main branch is not affected because the raw SQL column reference support has been removed in 06eec31 per the 4.0 deprecation life cycle. Thanks Joel Saunders for the report.
1 parent 8dc1cc0 commit 0bd57a8

4 files changed

Lines changed: 27 additions & 3 deletions

File tree

django/db/models/sql/constants.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
"""
22
Constants specific to the SQL storage portion of the ORM.
33
"""
4+
from django.utils.regex_helper import _lazy_re_compile
45

56
# Size of each "chunk" for get_iterator calls.
67
# Larger values are slightly faster at the expense of more storage space.
@@ -18,6 +19,7 @@
1819
'ASC': ('ASC', 'DESC'),
1920
'DESC': ('DESC', 'ASC'),
2021
}
22+
ORDER_PATTERN = _lazy_re_compile(r'[-+]?[.\w]+$')
2123

2224
# SQL join types.
2325
INNER = 'INNER JOIN'

django/db/models/sql/query.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,9 @@
3030
from django.db.models.query_utils import (
3131
Q, check_rel_lookup_compatibility, refs_expression,
3232
)
33-
from django.db.models.sql.constants import INNER, LOUTER, ORDER_DIR, SINGLE
33+
from django.db.models.sql.constants import (
34+
INNER, LOUTER, ORDER_DIR, ORDER_PATTERN, SINGLE,
35+
)
3436
from django.db.models.sql.datastructures import (
3537
BaseTable, Empty, Join, MultiJoin,
3638
)
@@ -1897,7 +1899,7 @@ def add_ordering(self, *ordering):
18971899
errors = []
18981900
for item in ordering:
18991901
if isinstance(item, str):
1900-
if '.' in item:
1902+
if '.' in item and ORDER_PATTERN.match(item):
19011903
warnings.warn(
19021904
'Passing column raw column aliases to order_by() is '
19031905
'deprecated. Wrap %r in a RawSQL expression before '

docs/releases/3.1.13.txt

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,16 @@ Django 3.1.13 release notes
66

77
Django 3.1.13 fixes a security issues with severity "high" in 3.1.12.
88

9-
...
9+
CVE-2021-35042: Potential SQL injection via unsanitized ``QuerySet.order_by()`` input
10+
=====================================================================================
11+
12+
Unsanitized user input passed to ``QuerySet.order_by()`` could bypass intended
13+
column reference validation in path marked for deprecation resulting in a
14+
potential SQL injection even if a deprecation warning is emitted.
15+
16+
As a mitigation the strict column reference validation was restored for the
17+
duration of the deprecation period. This regression appeared in 3.1 as a side
18+
effect of fixing :ticket:`31426`.
19+
20+
The issue is not present in the main branch as the deprecated path has been
21+
removed.

tests/queries/tests.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3134,6 +3134,14 @@ def test_invalid_order_by(self):
31343134
with self.assertRaisesMessage(FieldError, msg):
31353135
Article.objects.order_by('*')
31363136

3137+
def test_order_by_escape_prevention(self):
3138+
msg = (
3139+
"Cannot resolve keyword 'queries.name);' into field. Choices are: "
3140+
"created, id, name"
3141+
)
3142+
with self.assertRaisesMessage(FieldError, msg):
3143+
Article.objects.order_by('queries.name);')
3144+
31373145
def test_invalid_queryset_model(self):
31383146
msg = 'Cannot use QuerySet for "Article": Use a QuerySet for "ExtraInfo".'
31393147
with self.assertRaisesMessage(ValueError, msg):

0 commit comments

Comments
 (0)