Skip to content
KitploitKITPLOIT
工具博客
提交
工具博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

··订阅源·联系·隐私·© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
CVE-2021-35042 — 关于CVE-2021-35942的基础分析。Django中的SQL注入。 | Kitploit
工具/GitHubGitHub/zer0qs/cve-2021-35042
漏洞分析漏洞利用Web安全论文与研究学习与教育
GitHubzer0qs/cve-2021-35042

CVE-2021-35042

关于CVE-2021-35942的基础分析。Django中的SQL注入。

查看仓库
214年前尚未审核

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享

CVE-2021-35042: Django SQL注入漏洞

I. 概述

Django 是一个开源的 Web 应用程序框架,使用 Python 编写,基于 MVC(Model - View - Controller)模型构建。它最初是为了管理由 Lawrence 出版集团拥有的新闻内容网站而构建的,是一个 CMS(内容管理系统)软件。

Django 3.1.x -> 3.1.13 和 3.2.x -> 3.2.5 版本存在 SQL 注入漏洞。

导致此漏洞的原因是 QuerySet.order_by() 中对用户可控输入数据的过滤功能不足以防御 SQL 注入攻击。该漏洞可能被利用,允许攻击者执行未经授权的操作,从而导致敏感数据泄露。

CVE - IDCVE-2021-35042
严重性9.8 - 严重
CWE - IDCWE-89: SQL命令中特殊元素的不当中和('SQL注入')
漏洞发布日期2021年7月1日
受影响软件3.1.x < 3.1.13, 3.2.x < 3.2.5
是否需要认证不需要

II. 概述 x2

0x01. Django 的模型

在 Django 中,创建数据库表和定义字段是通过在 models.py 文件中声明一个模型类来完成的。在此示例中,我们声明了一个名为 Wolf 的表,以及一个名为 name 的字段。

0x02. Django 中的 QuerySet 和 Order_by()

Django 内置的 ORM 框架用于操作数据库,查询结果是一个集合,这个集合就是一个 QuerySet。

order_by(fields) 默认情况下,order_by() 返回一个 QuerySet,该 QuerySet 按照模型 Meta 中 ordering 选项指定的顺序进行排序。我们可以通过使用 order_by() 方法在每个查询中覆盖 order_by 条件。

示例

wolves = Wolf.objects.order_by('-name', 'id')

上述查询的结果将按 name 字段降序排序,然后按 id 字段升序排序。字段名 name 前面的负号表示结果按降序排序。

以下示例将根据用户输入的字段对返回结果进行排序,如果没有传入任何值,则按 id 字段排序。

结果

在 3.1 和 3.2 版本中,Django 允许将查询方法与表名结合到 order_by 查询中。这也是导致此漏洞的主要原因。

传入表名与正常传入字段名得到的结果相同

cve202135042_wolf 是表名

首先,应用程序直接调用 order_by() 函数,处理 order_by() 函数的代码定义在: django/db/models/query.py

order_by() 函数执行两件事

  1. 清除当前所有由 order_by() 调用的方法,并在 order_by 接收到不同值时清除传入的默认参数。
  1. 将参数传递给 order_by。add_ordering() 函数将执行此操作。
root@kitploit:~
def add_ordering(self, *ordering):
        """
        Add items from the 'ordering' sequence to the query's "order by"
        clause. These items are either field names (not column names) --
        possibly with a direction prefix ('-' or '?') -- or OrderBy
        expressions.

        If 'ordering' is empty, clear all ordering from the query.
        """
        errors = []
        for item in ordering:
            if isinstance(item, str):
                if '.' in item:
                    warnings.warn(
                        'Passing column raw column aliases to order_by() is '
                        'deprecated. Wrap %r in a RawSQL expression before '
                        'passing it to order_by().' % item,
                        category=RemovedInDjango40Warning,
                        stacklevel=3,
                    )
                    continue
                if item == '?':
                    continue
                if item.startswith('-'):
                    item = item[1:]
                if item in self.annotations:
                    continue
                if self.extra and item in self.extra:
                    continue
                # names_to_path() validates the lookup. A descriptive
                # FieldError will be raise if it's not.
                self.names_to_path(item.split(LOOKUP_SEP), self.model._meta)
            elif not hasattr(item, 'resolve_expression'):
                errors.append(item)
            if getattr(item, 'contains_aggregate', False):
                raise FieldError(
                    'Using an aggregate in order_by() without also including '
                    'it in annotate() is not allowed: %s' % item
                )
        if errors:
            raise FieldError('Invalid order_by arguments: %s' % errors)
        if ordering:
            self.order_by += ordering
        else:
            self.default_ordering = False
            

传递给 add_ordering() 的参数是一个数组。

例如,当参数按如下方式传递时: wolves = Wolf.objects.order_by( 'name' , 'id' ) 此时,应用程序将转换为数据库中的查询语句,如下所示:

root@kitploit:~
SELECT "cve202135042_wolf"."id", "cve202135042_wolf"."name" FROM "cve202135042_wolf" ORDER BY "cve202135042_wolf"."name" ASC, "cve202135042_wolf"."id" ASC

传入时,add_ordering 函数将检查数组中的每个元素,如果它是一个 string,将检查以下 5 种情况:

  1. if '.' in item: 它将检查这是否是一个带有列名的查询,并且该列在 SQL 语句中是否指定了表名。如果是,则会发出警告并 continue。
  2. if item == '?': 如果元素的值是 '?',则输出结果将随机排序,continue。
  3. if item.startswith('-'): 如果 item 以 '-' 字符开头,则查询结果将按 DESC(降序)排序。
  4. if item in self.annotations: 它检查是否包含注释,如果包含,则 continue。
  5. if self.extra and item in self.extra: 确定是否有额外补充,如果有则 continue。

经过 5 次检查后,参数继续传递给 self.names_to_path(item.split(LOOKUP_SEP), self.model._meta) 函数,以进一步检查它是否是一个有效的列名,如果有效,则将其添加到 Query 类的 self.ordering 中以进行进一步处理。

III. Django 中 SQL 注入漏洞的分析

0x31. 原因

Django 的 ORM 对插入查询的数据进行了非常严格的过滤,但这次导致 SQL 注入的源代码更改是因为作者假设如果列名是 UUID(通用唯一标识符)列,则 order_by 查询将无法执行。

这意味着如果传入的数据是 xxx-xxx-xxx-xxx(UUID 格式),则查询将无法执行。

更改前的代码

root@kitploit:~
# django/db/models/sql/constants.py 
ORDER_PATTERN  =  _lazy_re_compile ( r '\?|[-+]?[.\w]+$' )

# django/db/models/sql/query.py 
def  add_ordering ( self ,  * ordering ): 
        errors  =  [] 
        for  item  in  ordering : 
            if  isinstance ( item ,  str )  and  ORDER_PATTERN . match ( item ): 
                if  '.'  in  item : 
                    warnings . warn ( 
                        'Passing column raw column aliases to order_by() is ' 
                        'deprecated. Wrap %r in a RawSQL expression before '
                        'passing it to order_by().'  %  item , 
                        category = RemovedInDjango40Warning , 
                        stacklevel = 3 , 
                    ) 
            elif  not  hasattr ( item ,  'resolve_expression' ): 
                errors . append ( item ) 
            if  getattr ( item ,  'contains_aggregate' ,  False ): 
                raise  FieldError ( 
                    'Using an aggregate in order_by() without also including ' 
                    'it in annotate() is not allowed: %s ' %  item 
                ) 
        if  errors : 
            raise  FieldError ( 'Invalid order_by arguments: %s '  %  errors ) 
        if  ordering : 
            self . order_by  +=  ordering 
        else : 
            self . default_ordering  =  False

从上面的代码可以看出,如果参数匹配 ? 或以 - 开头且后跟常规字符或 .,则查询才会执行。

因此,当列名是 UUID 时,它将是一个无效值,无法传入 order_by。 此处理代码的更改已被接受,更改如下: https://github.com/charettes/django/commit/513948735b799239f3ef8c89397592445e1a0cd5

它使用了 self.name_to_path 函数来验证输入数据。

但是,在检查到 item 中包含 . 后,它会将其视为带有表名的查询,并执行 continue 命令,从而直接跳过使用 self.name_to_path 函数来检查数据的有效性。

在 get_order_by 函数中处理 . 的代码如下: django/db/models/sql/compiler.py

root@kitploit:~
if  '.'  in  field : 
    table ,  col  =  col . split ( '.' ,  1 ) 
    order_by . append (( 
            OrderBy ( 
                RawSQL ( ' %s . %s '  %  ( 
                self . quote_name_unless_alias ( table ),  col ),  [ ]), 
                descending = descending 
            ),  False )) 
    continue

self.quote_name_unless_alias 函数处理表名,过滤有效的表名并跳过对列名的过滤,因此我们可以插入 SQL 注入语句。

0x32. 补丁

在当前 Django 4.0 版本中,使用 . 按表名查询已被移除,不再支持,补丁已针对 3.1 和 3.2 版本发布。3.2 -> 3.2.4 和 3.1 -> 3.1.12 版本受到影响。 3.2.x 修复 CVE-2021-35042 -- 防止了 QuerySet.o… 中的 SQL 注入

3.1.x 修复 CVE-2021-35042 -- 防止了 QuerySet.o… 中的 SQL 注入

修改非常简单,旧的 ReGex 数据检查已恢复。

0x33. 修复

将 Django 更新到不受影响的版本。

IV. 演示

0x41. 环境

Docker & Docker-compose

0x42. 设置

  1. git clone https://github.com/WynSon/CVE-2021-35042.git
  2. 运行 ./setup.sh 进行初始设置
  3. sudo docker-compose up --build
  4. sudo docker exec -it cve-2021-35042_web_1 python manage.py makemigrations cve202135042
  5. sudo docker exec -it cve-2021-35042_web_1 python manage.py migrate
  6. 访问 http://localhost:8000/load_example_data 加载示例数据:
  7. 包含易受攻击参数的路由:http://localhost:8000/wolves/ http://localhost:8000/wolves/?order_by=name

安装完成后的界面

0x43. 漏洞利用

条件: 为了能够利用漏洞,我们必须以某种方式知道表名 :))

注入语句时,我们必须知道表名才能执行 SQLi 语句。

当输入错误的表名时

当输入正确的表名时,orderby 查询正常执行。

此时的语句将变为 SELECT "cve202135042_wolf"."id", "cve202135042_wolf"."name" FROM "cve202135042_wolf" ORDER BY ("cve202135042_wolf"."name") ASC

此时,我们可以结束前面的 order_by 语句并插入一条 SQL 语句进行利用。

SELECT "cve202135042_wolf"."id", "cve202135042_wolf"."name" FROM "cve202135042_wolf" ORDER BY ("cve202135042_wolf"."name"); SELECT * from cve202135042_wolf where id =1; --) ASC

V. 参考

https://www.djangoproject.com/weblog/2021/jul/01/security-releases/ https://xz.aliyun.com/t/9834 https://www.bugxss.com/vulnerability-report/3095.html https://blankheart.top/2022/04/07/cve-2021-35042/ https://itcn.blog/p/1648921763575859.html https://github.com/YouGina/CVE-2021-35042

下载工具