前言
考试前翻Python
的组件漏洞时发现Django
考完SQL
存在漏洞,抽空后抽空相关的漏洞,分别是CVE-2020-7471
、CVE-2021-35042
和CVE-2022-28346
。
姜戈简介
Django 是一个高级 Python Web 框架,它鼓励快速开发和简洁、实用的设计。它由经验丰富的开发人员构建,解决了 Web 开发的大部分麻烦,因此您可以专注于编写应用程序,而无需重新发明轮子。它是免费和开源的。

CVE-2020-7471
漏洞简介
1.11.28 之前的 Django 1.11、2.2.10 之前的 2.2 和 3.0.3 之前的 3.0 如果将不受信任的数据用作 StringAgg 分隔符,则允许 SQL 注入(例如,在 Django 应用程序中,将数据下载作为用户的一系列行提供-指定的列分隔符)。通过将适当设计的分隔符传递给 contrib.postgres.aggregates.StringAgg 实例,可以打破转义并注入恶意 SQL。

漏环境
参考27个环境CVE-2020-1。
漏洞分析
在漏洞描述中描述该漏洞的核心是StringAgg
聚合函数的delimiter
参数SQL
存在注入漏洞。通过查找Django
的
commit
记录,在官方对的修复代码中可以看到,漏洞函数from django.contrib.postgres.aggregates import StringAgg
模块位于其中。

官方修复通过引入from django.db.models import Value
的Value
来处理来该部署中的漏洞:
delimiter_expr = 值(str (分隔符))
后续可以在中查看django.db.models
的函数Value
中查看、Value
函数处理、后续处理的参数加入到sql parameter list
之后会进Django
组过滤机制的过滤、定点来sql
注入漏洞。

漏洞利用点是StringAgg
聚合函数的delimiter
参数,官方文档中使用了简单的权利保护函数进行说明,在它的级联中使用了它的级联划分delimiter
符。

通过为单项声明时会Fuzz
发现delimiter
报错信息,且通过打印的报错可以,未经验证的转义就嵌入到单项声明sql
中。
def fuzz ():
symbol_str = "!@#$%^&*()_+=-| \\\" ':;?/>.
for c in symbol_str :
results = Info 。objects .all ( ) .values ( ' gender ' ) .annotate ( mydefinedname = StringAgg ( ' name' , delimiter = c )) try : for e in results : pass except IndexError :
pass
except Exception as err :
print ( "[+] 报错信息: " , err )
print ( "[+] 漏洞分隔符: " , c )

根据报错信息,在_execute
函数中打断点。

当遍历完数据库中的数据后,进行Fuzz
操作,观察加入了delimiter
为单引号取值的sql
。

此时sql
是个字符串,因此会产生转义号,该sql
语句在postgres
中的执行语句为:
选择 “vuln_app_info” 。"gender" , STRING_AGG ( "vuln_app_info" . "name" , ''') AS "mydefinedname" FROM "vuln_app_info" GROUP BY "vuln_app_info"."gender"
尝试delimiter
设置')--
错误,可以看到结果显示其结果的语句,查看报告信息,注释了FROM
语句。

构造exp
如下:
- \ ') AS "demoname" FROM "vuln_app_info" GROUP BY "vuln_app_info"."gender" LIMIT 1 OFFSET 1 --

CVE-2021-35042
漏洞简介
如果 order_by 是来自 Web 应用程序客户端的不受信任的输入,则 3.1.13 之前的 Django 3.1.x 和 3.2.5 之前的 3.2.x 允许 QuerySet.order_by SQL 注入。

漏环境
35 好环境CVE-2021-42 .
漏洞分析
可知漏洞信息,先跟进order_by
函数,该函数先调用clear_ordering
函数清除Query
类中的self.order_by
参数,调用add_ordering
函数self.order_by
参数增加。

通过order_by
函数代码环境的参数为调用函数中的参数,如下所示SQL
:
查询 = 请求。得到。获取('order_by' , 默认= 'vuln' )res = User 。对象。order_by (查询)
选择 “app_user” 。“vuln” 、 “app_user” 。"order_by" FROM "app_user" ORDER BY "app_user" 。
“order_by” ASC , “app_user” 。“漏洞” ASC
继续进行职能, 则职能add_ordering
对ordering
作为绩效之后进行鉴定, 如果item
继续进行五次鉴定:
if '.' in item
: 判断是否为带列的查询,SQL
语句中允许使用定义表名的列,例如order by (user.name)
,即根据user
表下的name
字段进行示例。该判断方法将在Django 4.0
之后被警告删除,因此成功之后通过warning
,之后进行continue
。
if item == '?'
当item
的字符串?
时,可用order by
的值进行语法
RAND()
,显示显示SQL
的返回数据continue
。
if item.startswith('-')
:观感item
为字符串的接续结果,则当顺序排列-
时,会显示接续的连续order by
查询上的正序表示。DESCASC-
if item in self.annotations
: 鉴定时附有注明continue
。直接,有话
if self.extra and item in self.extra
: 判断是否有额外添加,有直接的话continue
。
五鉴定之后,进入到是否为有效的参数之后,将所有参数的self.names_to_path(item.split(LOOKUP_SEP), self.model._meta)
当前item
列名中的ordering
类别,进行到处理。Queryself.order_by

在第一次进行判断中,if '.' in item
进行order by
更好的地表查询能力查询,如果能够区分的话,如果列是否为表带表continue
,continue
则直接跳过对列self.names_to_path
的有效性。后续处理带字符串.
的代码,位于文件django/db/models/sql/compiler.py
的get_order_by
函数中,核心代码:
如果 '。' 在 字段中:
表, col = col 。拆分('.' , 1 )
order_by 。append ((
OrderBy (
RawSQL ( ' %s . %s ' % ( self . quote_name_unless_alias ( table ), col ), []),
descending = descending
), False ))
继续
代码中函数表名,使用函数self.quote_name_unless_alias
表名,使用强制处理来强制处理,后面表面则确实没有表面处理,则可以处理的列处理行为,SQL
注入。
最后参数app_user.name) --
数据库的语句为:
选择 ` app_user` 。_ ` id`
,` app_user` 。_ _ ` name`FROM`app_user`ORDER BY ( ` app_user`.name ) -- ) ASC LIMIT 21 _ _ _ _ _
使用)
以下方式进行最终的最终实现payload
:http://127.0.0.1:8000/vuln/?order_by=vuln_app_user.name);select%20updatexml(1,%20concat(0x7e,(select%20@@version)),1)%23

CVE-2022-28346
漏洞简介
在 2.2.28 之前的 Django 2.2、3.2.13 之前的 3.2 和 4.0.4 之前的 4.0 中发现了一个问题。QuerySet.annotate()、aggregate() 和 extra() 方法通过精心制作的字典(带有字典扩展)作为传递的 **kwargs 在列别名中进行 SQL 注入。

漏环境
28个循环好环境CVE-2022-46。
漏洞分析
查找Django
的commit
记录示例,在官方对的修复代码中可以查看测试用例。

annotate
由漏洞利用,在annotate
函数中首先会调用函数并跟进漏点_annotate
并调用kwargs
。

annotate
函数在完成对kwargs.values()
合法性更新等操作,之后将kwargs
遍历annotations
中annotations
的元素调用add_annotation
进行数据聚合。

然后,继续add_annotation
函数调用resolve_expression
解析表达式,并在此同时对这些参数进行相应的检查

继续跟进,最终进入到db.models.sql.query.py:resolve_ref
会中resolve_ref
获取annotations
中的元素,并将其转换后带到查询中的条件中,最后其结果通过
transform_function
聚合到一个Col
对象中。

执行、返回db.models.query.py:_annotate
、sql
语句、将结果返回到QuerySet
中进行展示。

参考
CVE-2020-7471漏洞详细分析原理以及POC
Django CVE-2021-35042 order_by SQL注入分析
已发布 Django 安全版本:4.0.4、3.2.13 和 2.2.28
来源:先知(https://xz.aliyun.com/t/11422#toc-0)
注:如有侵权请联系删除

欢迎大家加群一起讨论学习和交流

快乐要懂得分享,
才能加倍的快乐。