社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Django

Django SQL 引入逻辑分析

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

前言

考试前翻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
 
227 次点击