# 路径没有越界,读取为何仍会挂起?Werkzeug 与 Windows 文件名语义
路径没有越界,读取为何仍会挂起?Werkzeug 与 Windows 文件名语义
背景与时间线:新收录不等于新攻击
本次选题的时效依据是 GitHub 已审核数据库在近 72 小时的收录。项目此前已披露相关问题,不能把数据库日期当作攻击发生日期。以下事实以安全公告及其关联的项目发布资料为依据;后续工程分析和建议不代表厂商确认的事故结论。
| 核验项 | 结果 |
|---|---|
| 漏洞编号 | CVE-2026-102598 |
| 项目公告日期 | 2026-09-27 |
| GitHub 已审核数据库收录日期 | 2026-10-05 |
| 受影响与最低修复边界 | Werkzeug ❤️.1.9;最低修复版本 3.1.9;本问题涉及 Windows 与 NTFS 条件 |
| 攻击发生时间 | 所引用资料未提供可确认的现实攻击时间 |
技术原理与信任边界
官方公告确认 safe_join 对带空 ADS 标记的 Windows 特殊设备名处理不完整;使用 send_from_directory 的相关 Windows/NTFS 应用可能在读取时挂起。3.1.9 发布说明列出该修复,PR #3309对应名称过滤更新。
这是文件名语义问题,不能直接描述成目录穿越、任意文件读取或 RCE。即使规范化后的字符串仍位于指定目录,操作系统也未必把末尾组件当作常规文件。路径边界、对象类型和读取预算是三个不同问题。
工程分析:跨平台服务不宜让业务 ID 直接成为任意路径。更稳妥的设计是将不透明文件 ID 映射到服务端生成的名字,再单独记录用户展示名称。这样能明显减少必须解释的路径语法,但不能替代底层文件打开时的对象检查和权限控制。
影响范围:从依赖存在到路径可达
依赖清单命中是调查入口,还需要确认相关功能是否启用、输入能否被不可信主体影响、程序以何种权限运行,以及产物或状态是否跨任务复用。本文不把潜在后果写成已经发生的事故,也不以公开说明等同于在野利用证据。
建议保留一份服务级判定记录:运行版本、调用点、输入来源、权限边界和处置负责人。由开发确认调用路径,安全团队确认不可信输入如何进入,平台团队确认补丁是否覆盖运行实例。这比单纯将漏洞工单标记为“依赖已升级”更有验证价值。
防御性实验:只验证安全不变量
下列 Python 3 示例仅处理本地内存数据,不攻击真实服务,可独立运行。
import re
def allowed_component(name):
# 教学模型:主动限制为保守的 ASCII 文件名子集。
if not re.fullmatch(r"[A-Za-z0-9_-]+(?:\.[A-Za-z0-9_-]+)*", name):
return False
base = name.split('.', 1)[0].upper()
reserved = {'CON', 'PRN', 'AUX', 'NUL'}
reserved.update('COM' + str(i) for i in range(1, 10))
reserved.update('LPT' + str(i) for i in range(1, 10))
return base not in reserved
assert allowed_component('report-2026.txt')
assert not allowed_component('NUL')
assert not allowed_component('CON.txt')
assert not allowed_component('report:')
assert not allowed_component('../report')
print("5 项纯字符串检查通过")
示例不会打开任何路径;其规则比一般文件系统更严格,不支持 Unicode 文件名、路径分隔符和 ADS。它用于说明可接受子集策略,不是 Werkzeug 补丁的完整重写。若业务要支持更丰富的文件名,应使用修复后的库与操作系统语义测试,而非随意扩大这段正则。
测试还应包括合法输入,确保防护不是通过关闭全部功能而获得表面成功。负向用例要断言拒绝发生的位置及副作用,而不只是断言最终返回错误。若测试仅验证“抛出了异常”,异常前已经发生的网络连接、内存分配或代码生成仍可能被漏掉。
修复与防护建议
盘点 Windows 上实际提供文件下载的服务及 Werkzeug 运行版本,升级到包含修复的版本。Linux 部署不能据此被判为本漏洞可利用,但共享代码库仍应保留 Windows CI 回归任务。
把路径测试分成目录边界、名称语义、符号链接、普通文件类型和取消清理五组。测试特殊名称时优先验证拒绝结果,避免打开设备。对下载设置超时和工作进程隔离,并确认客户端断开后服务端读取能结束。仅在反向代理上设置超时,可能只关闭连接而没有释放后端线程。
交付验收清单
| 责任方 | 应交付的证据 |
|---|---|
| 研发 | 相关调用路径说明、合法与拒绝用例、版本升级差异 |
| 安全 | 输入信任边界、历史暴露判断、剩余风险记录 |
| 平台 | 实际运行版本、部署范围、失败回滚与监控方案 |
修复关闭当前缺陷后,仍应把相同类型的边界检查纳入后续开发约束。没有异常日志可能意味着未发生攻击,也可能意味着没有记录到关键阶段;应结合暴露条件解释证据,避免作出超出可见范围的结论。
总结
本案例的实用价值,是把依赖告警转化成可验证的工程问题:哪个输入获得了超出预期的解释,哪一步必须先执行校验,以及升级后哪些运行对象需要重新确认。版本修复、调用链审查和回归测试应共同构成关闭风险的依据。
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐


所有评论(0)