CVE |
您所在的位置:网站首页 › poc原理验证 › CVE |
这几天疫情爆发,只能待在家里为社会多做些贡献,一天深夜无意逛安全资讯的时候发现最新的一个漏洞:CVE-2020-7471 Potential SQL injection via StringAgg(delimiter)。漏洞是 django 的,于是我将漏洞编号拿到 google 查找了一番,发现并没有找到任何关于这个漏洞的详细说明和利用 POC,于是我动手写下了这篇文章。 本文主要贡献: 总结了该漏洞的起因和背景,并深入分析了官方的修复方案详细分析了 这个 SQL 漏洞,并给出利用姿势在本文公开自己搭建的漏洞环境和 POC漏洞原因摘录 CVE-2020-7471 对这个漏洞的描述: Django 1.11 before 1.11.28, 2.2 before 2.2.10, and 3.0 befor ![]() e 3.0.3 allows SQL Injection if untrusted data is used as a StringAgg delimiter (e.g., in Django applications that offer downloads of data as a series of rows with a user-specified column delimiter). By passing a suitably crafted delimiter to a contrib.postgres.aggregates.StringAgg instance, it was possible to break escaping and inject malicious SQL. 可以看见这个漏洞的核心是 StringAgg 聚合函数的 delimiter 参数存在 SQL 注入漏洞。但是很快,为什么存在漏洞?怎么利用这个漏洞?二个问题在我心中油然而生,好奇心驱使我继续往下探索: 官方修复首先在 Github 仓库查找 django 的 commit 记录,在这里不难发现官方对其的修复: https://github.com/django/django/commit/eb31d845323618d688ad429479c6dda973056136 ![]() 从这里我们知道几个信息,漏洞函数位于下面的模块之中 from django.contrib.postgres.aggregates import StringAgg官方对 delimiter 使用如下语句处理来防御 django Value(str(delimiter))为什么这种方式能防御呢?首先补充一个知识点,如果你熟悉 django 或者至少做过 django 渗透,你应该知道在 django 开发中编写查询操作的时候,正确的做法是用下面的代码段: sql = "SELECT * FROM user_contacts WHERE username = %s"user = 'zhugedali'cursor.execute(sql, [user])django会根据你所使用的数据库服务器(例如PostSQL或者MySQL)的转换规则,自动转义特殊的SQL参数。如果你的查询代码像下面这种写法就存在注入的风险: sql = "SELECT * FROM user_contacts WHERE username = %s" % 'zhugedali'cursor.execute(sql)那么回到正题,为什么 Value 函数可以解决 SQL 注入隐患,我们跟进 django 的源码查看: ![]() 注释写的非常清楚,Vlue处理过的参数会被加到sql的参数列表里,之后会被 django 内置的过滤机制过滤,从而防范 SQL 漏洞。 到这里想必很多读者还是很好奇对于存在漏洞的版本我们如何去利用 SQL 漏洞呢?这就需要费点时间去搭建环境并从源码层面分析出 SQL 漏洞点的上下文语句情况。 漏洞利用我搭建的环境如下: django 3.0.2postgres 10.11-3python 3.6搭建环境的时候注意 django 配置好 settings.py 文件,并初始化 postgres 的数据库和数据表,文末会提供环境。 首先研究一下 StringAgg 的用法,直接阅读官方手册: https://docs.djangoproject.com/en/3.0/ref/contrib/postgres/aggregates/ django.contrib.postgres.aggregates 提供 postggres 的聚合函数,其中的 StringAgg 类的参数如下: ![]() 简单来讲他会将输入的值使用 delimiter 分隔符级联起来,Django 的 Model 类如何使用这个让我摸索了一会,我直接给出后面会提供的 POC 里面的示例: Info.objects.all().values('gender').annotate(mydefinedname=StringAgg('name', delimiter="-"))这个查询操作就是查询 Info 对应的 postgres 数据表的 gender 列,并将 name 列使用横线连接聚合,输入如下: ![]() 为了测试出 delimiter 是如何导致SQL 注入的,我首先编写了一段 FUZZ 程序用于引发程序报错: for c in "!@#$%^&*()_+=-|\\\"':;?/>. |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |