Django CVE-2022-28346 SQL注入分析

2022-05-12点击量:8178


前言

最近在看CNVD时无意间看到两条关于Django的最新漏洞通告,随即打开看了一下,大概意思是说Django在2.2.28 版本之前的2.2版本、3.2.13版本之前的3.2版本、4.0.4版本之前的4.0版,本使用QuerySet.annotate() aggregate() extra()数据聚合函数时会导致SQL注入问题。由于笔者平时开发一些平台多半也是使用Django,所以便尝试进行分析了一下,如有描述不当之处,还望提出建议修改斧正。


影响版本

Django Django >=2.2,<2.2.28
Django Django >=3.2,<3.2.13
Django Django >=4.0,<4.0.4

 

环境构建

Python: 3.7.9
Django: 3.2.11

 

目录结构

202205120958058031.png

models.py

views.py

urls.py

settings.py

或者使用笔者构建好的环境:

http://github.com/DeEpinGh0st/CVE-2022-28346

 

漏洞复现

初始化项目

1.python manage.py makemigrations
2.python manage.py migrate
3.访问http://x.x.x.x:8000/ 初始化数据

触发

访问
http://x.x.x.x:8000/demo?field=demo.name" FROM "demo_user" union SELECT "1",sqlite_version(),"3" --

202205121000361656.png

 

漏洞分析

老规矩,分析前可以先看看官方在修复的commit中有没有给出测试用例

在http://github.com/django/django/commit/2044dac5c6968441be6f534c4139bcf48c5c7e48中看到官方在测试组件中给出了基本的测试用例。

202205121001431388.png

我们可以根据官方给出的代码编写相应的代码进行调试和分析。

在views.py的annotate打入断点后,来到db.models.query.py:__init__,进行QuerySet的初始化。

202205121002084945.png

在初始化QuerySet后,会来到db.models.query.py:annotate开始执行聚合流程,在annotate中首先会调用_annotate并传入kwargs。

202205121003338232.png

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

202205121003534432.png

跟进add_annotation(print是笔者为了分析自己加入的)。

202205121004186482.png

add_annotation继续调用resolve_expression解析表达式,在此处并没有对传入的聚合参数进行相应的检查。在经过一系列调用后,最终会来到db.models.sql.query.py:resolve_ref

resolve_ref会获取annotations中的元素,并将其转换后带入到查询的条件中,最后其结果通过transform_function聚合到一个Col对象中,可以看到聚合之后的结果。

202205121005054073.png

返回到db.models.query.py:_annotate可以看到具体聚合后数据值,以及执行的sql语句。

202205121005262305.png

最后将结果返回到QuerySet中进行展示。

202205121005489899.png

 

修复

在漏洞公开后,Django官方随即对项目进行了修复。

202205121006137910.png

在add_annotation中加入了check_alias对聚合参数进行检查。

 

参考

http://github.com/django/django/commit/2044dac5c6968441be6f534c4139bcf48c5c7e48

http://www.cnvd.org.cn/flaw/show/CNVD-2022-31838