社区所有版块导航
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

CVE-2020-7471 Django StringAgg SQL Injection漏洞复现

安全漏洞环境学习 • 5 年前 • 337 次点击  

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-psycopg2sudo 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 makemigrationspython3 manage.py migratepython3 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/7218https://github.com/Saferman/CVE-2020-7471



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