
Django SQL injection CVE-2022-28346 analysis
前言
最近在看CNVD时无意间看到两条关于Django
的最新漏洞通告,随即打开看了一下.大概意思是说Django
在2.2.28
版本之前的2.2
版本、3.2.13
版本之前的3.2
版本、4.0.4
版本之前的4.0
版本使用QuerySet.annotate() aggregate() extra()
数据聚合函数时会导致SQL注入问题.由于笔者平时开发一些平台多半也是使用Django
,所以便尝试进行分析了一下.如有描述不当之处,还望大佬们斧正.
影响版本
1 |
|
环境构建
1 |
|
目录结构
models.py
1 |
|
views.py
1 |
|
urls.py
1 |
|
settings.py
1 |
|
或者使用笔者构建好的环境
https://github.com/DeEpinGh0st/CVE-2022-28346
漏洞复现
初始化项目
1 |
|
触发
1 |
|
漏洞分析
老规矩,分析前可以先看看官方在修复的commit中有没有给出测试用例
在https://github.com/django/django/commit/2044dac5c6968441be6f534c4139bcf48c5c7e48
中看到官方在测试组件中给出了基本的测试用例
我们可以根据官方给出的代码编写相应的代码进行调试和分析.
在views.py的annotate打入断点后,来到db.models.query.py:__init__
,进行QuerySet
的初始化
在初始化QuerySet
后,会来到db.models.query.py:annotate
开始执行聚合流程,在annotate
中首先会调用_annotate
并传入kwargs
_annotate
在完成对kwargs.values()
合法性校验等一系列操作后,将kwargs
更新到annotations
中,随后遍历annotations
中的元素调用add_annotation
进行数据聚合
跟进add_annotation
(print是笔者为了分析自己加入的)
add_annotation
继续调用resolve_expression
解析表达式,在此处并没有对传入的聚合参数进行相应的检查.在经过一系列调用后,最终会来到db.models.sql.query.py:resolve_ref
resolve_ref
会获取annotations
中的元素,并将其转换后带入到查询的条件中,最后其结果通过transform_function
聚合到一个Col
对象中
可以看到聚合之后的结果
返回到db.models.query.py:_annotate
可以看到具体聚合后数据值,以及执行的sql
语句
最后将结果返回到QuerySet中进行展示
修复
在漏洞公开后,django
官方随即对项目进行了修复
在add_annotation
中加入了check_alias
对聚合参数进行检查
参考
https://github.com/django/django/commit/2044dac5c6968441be6f534c4139bcf48c5c7e48