0X1 漏洞概述
近日,Django 官方发布安全通告公布了一个通过StringAgg(分隔符)的潜在SQL注入漏洞(CVE-2020-7471)。
如果将不受信任的数据用作StringAgg分隔符,则部分版本的 Django将允许SQL注入。
通过将精心设计的分隔符传递给contrib.postgres.aggregates.StringAgg实例,可以打破转义并注入恶意SQL。
受影响Django版本:
1.11 到 1.11.28(不含)
2.2 到 2.2.10(不含)
3.0 到 3.0.3(不含)
目前已存在针对该漏洞的 PoC。
0X2 环境搭建
系统:Ubuntu18.04
安装django,这里我选择的是2.2版本
安装postgres数据库
进入psql中,创建数据库,并修改用户密码
后面我们使用django创建项目的时候,需要关联psql,这里需要安装psycopg2,使用命令如下:
sudo apt-get install python3-psycopg2
sudo apt-get install libpq-dev
这样数据库环境就可以了。
然后我们使用django创建项目和应用,命令如下:
django-admin startproject sql 创建项目
django-admin startapp vul_app 创建应用
创建应用要在创建的项目目录中创建,完成之后目录结构如下所示:
然后修改settings.py文件,注册应用到项目中
并修改数据连接配置
DATABASES = {
'default': {
#'ENGINE': 'django.db.backends.sqlite3',
#'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'test', # 数据库名称
'USER': 'postgres',
'PASSWORD': 'postgres', # 数据库用户密码
'HOST': '127.0.0.1', # 数据库地址
'PORT': '5432',
}
}
保存之后,初始化数据库和表,命令如下:
python3 manage.py makemigrations
python3 manage.py migrate
python3 manage.py runserver 0.0.0.0:80
最后一条命令是启动环境命令
打开浏览器即可访问
0X3 漏洞分析
在github官方查看django的commit记录,不难发现:
从上面的代码中,我们知道漏洞函数位于模块StringAgg之中
from django.contrib.postgres.aggregates import StringAgg
官方对 delimiter 使用Value(str(delimiter))处理来防御 django。
为什么这种方式能防御呢?因为在 django开发中编写查询操作的时候,正确的做法是用下面的代码段:
sql = "SELECT * FROM user_contacts WHERE username = %s"
user = 'helloworld'
cursor.execute(sql, [user])
django会根据你所使用的数据库服务器(例如PostSQL或者MySQL)的转换规则,自动转义特殊的SQL参数。如果你的查询代码像下面这种写法就存在注入的风险:
sql = "SELECT * FROM user_contacts WHERE username = %s" % 'helloworld'
cursor.execute(sql)
而跟进Django的源码查看是可以发现问题的:
Vlue处理过的参数会被加到sql的参数列表里,之后会被 django 内置的过滤机制过滤,从而防范 SQL 漏洞。
0X4 漏洞利用
根据其他安全员发布的POC,这里使用Fuzzing测试找到delimiter导致SQL注入的原因是在过滤单引号引起的,我们在创建的应用module中需要添加一个数据模型,用来显示注入前后数据的返回结果,如下所示:
然后使用Saferman的CVE-2020-7471脚本测试,链接如下:
https://github.com/Saferman/CVE-2020-7471
将CVE-2020-7471.py放在项目根目录中,并修改脚本关联的环境配置文件
修改完成后测试:
前后数据不一致说明注入漏洞存在,不过如果还想将数据库中的用户数据进一步提取出来,就进一步需要写不同的数据模型方法了。
0X5 加固修复
升级到Django最新版3.0.3即可。
0X6 参考链接
https://xz.aliyun.com/t/7218
https://github.com/Saferman/CVE-2020-7471