Py学习  »  Django

Django SQL 引入逻辑分析

衡阳信安 • 3 年前 • 216 次点击  

前言

考试前翻Python的组件漏洞时发现Django考完SQL存在漏洞,抽空后抽空相关的漏洞,分别是CVE-2020-7471CVE-2021-35042CVE-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 ValueValue来处理来该部署中的漏洞:

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_orderingordering作为绩效之后进行鉴定, 如果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 更好的地表查询能力查询,如果能够区分的话,如果列是否为表带表continuecontinue则直接跳过对列self.names_to_path的有效性。后续处理带字符串.的代码,位于文件django/db/models/sql/compiler.pyget_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 _ _ _ _ _       


使用)以下方式进行最终的最终实现payloadhttp://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

漏洞分析

查找Djangocommit记录示例,在官方对的修复代码中可以查看测试用例。

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

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

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

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

执行、返回db.models.query.py:_annotatesql语句、将结果返回到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)

注:如有侵权请联系删除






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

快乐要懂得分享,

才能加倍的快乐。


Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/135596
 
216 次点击