| 字段 | 详情 |
|---|---|
| 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 |
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 存储中反序列化模型权重张量。
.keras 模型归档的生产或研究流水线均易受攻击| 上下文 | 风险 |
|---|
HDF5 文件格式将张量元数据(包括形状声明)与实际数据字节分开存储。当 KerasFileEditor._extract_weights_from_store() 遇到数据集条目时,它会读取声明的形状,并调用 NumPy 在从磁盘读取任何数据之前预分配相应维度的数组。
由于形状是元数据,一个极小的 HDF5 文件可以声明一个需要 PB 级内存的形状,而文件本身只有几 KB 大小。文件大小与分配大小的比率使其成为一种高效的放大攻击。
例如 (1000000, 1000000, 1000000) 且 dtype 为 32 位浮点的形状将请求约 4,000 PB 的内存。操作系统内存不足杀手(OOM killer)或 Python 分配器将几乎立即导致进程崩溃。
# keras/src/saving/file_editor.py (pre-fix, simplified)
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
# Step 1: Create a minimal HDF5 weights file with a hostile shape declaration
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)
# Step 2: Package into a valid .keras archive structure
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")
# trigger.py
import keras
print("[+] Loading malicious model...")
# The crash occurs at load time — no inference required
model = keras.saving.load_model("malicious_model.keras")
print("[-] This line is never reached — interpreter has crashed")
预期结果: Python 解释器以 MemoryError 终止,或在加载完成前被操作系统内存不足处理器杀死。
可观察症状:
load_model() 或 load_weights() 期间发生 Python 解释器崩溃或 MemoryErrorh5dump 检测到声明了超大数据集形状的异常 HDF5 文件该漏洞由研究人员(HyperPS / Sarvesh Patil)在 PR #21880 中修复,于 2025年12月29日 合并到 keras-team:master,由 Keras 维护者 hertschuh 审阅并批准。
该补丁修改了 keras/src/saving/file_editor.py 中的 KerasFileEditor._extract_weights_from_store(),在任何内存分配发生之前增加以下保护措施:
inner_path 处理该修复与所有有效的 Keras 权重文件向后兼容。
# keras/src/saving/file_editor.py (post-fix logic, simplified)
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."
)
通过 pip 升级:
pip install --upgrade keras
验证已安装版本:
python -c "import keras; print(keras.__version__)"
预扫描 HDF5 权重文件中的可疑形状:
h5dump --header model.weights.h5 | grep -i "DATASPACE"
本仓库仅在教育、研究和防御性安全目的下记录 CVE-2026-0897。提供概念验证代码和技术细节是为了帮助开发人员、安全工程师和系统管理员理解、评估和修复此漏洞。
未经明确授权,使用此信息对系统、服务或个人造成损害是非法且不道德的。作者对滥用本文所含信息不承担任何责任。
贡献者 @mohitf070304
| 指标 | 值 | 含义 |
|---|
| 攻击向量 (AV) | 网络 | 可通过分发的模型文件远程利用 |
| 攻击复杂度 (AC) | 低 | 无需特殊条件或竞态条件 |
| 攻击要求 (AT) | 无 | 无需前置部署配置 |
| 所需权限 (PR) | 无 | 无需身份验证或账户 |
| 用户交互 (UI) | 被动 | 受害者必须加载恶意的 .keras 归档 |
| 受影响系统可用性 (VA) | 高 | Python 解释器崩溃;服务完全不可用 |
| 受影响系统机密性 (VC) | 无 | 无数据泄露 |
| 受影响系统完整性 (VI) | 无 | 无数据篡改 |
| 后续系统影响 (SC/SI/SA) | 无 | 影响仅限于加载过程 |
接受用户上传 .keras 文件的公共模型服务 API | 攻击者通过单个请求使推理服务崩溃 |
| 托管社区模型下载的机器学习平台(如 Hugging Face) | 被投毒的模型会对任何下载并加载它的研究人员造成拒绝服务 |
| 联邦学习环境 | 恶意参与者分发特制的权重文件,使协调器或对等节点崩溃 |
| 加载模型检查点的 CI/CD 流水线 | 被入侵或被替换的检查点导致流水线故障和不可用 |
| 在运行时热重载模型的聊天机器人或 NLP 服务 | 单个恶意重载请求即可使服务宕机 |
| 合并提交 | 7360d4f |
| 向后移植请求(3.12.x) | Issue #22031 |
| 操作 | 详情 |
|---|
| 升级 Keras | 更新到包含 PR #21880 修复的版本(3.13.0 之后的 master 构建或任何官方修补版本) |
| 不要加载不受信任的模型文件 | 未经事先完整性验证,切勿从不受信任、未经验证或社区来源的位置加载 .keras 或 .weights.h5 文件 |
| 验证文件完整性 | 加载前对照发布者提供的哈希验证模型归档的 SHA-256 校验和 |
| 使用 h5dump 预扫描 | 在 Keras 中加载 HDF5 文件之前,使用 h5dump --header <file> 检查数据集形状元数据 |
| 最小权限 | 在受限操作系统用户下运行模型服务进程,并通过 cgroups 或 ulimit 强制执行内存限制,以限定爆炸半径 |
| 容器化 | 在具有内存限制的沙盒容器中隔离模型加载,防止单次崩溃影响其他服务 |
| 监控内存 | 对模型加载操作实施监控,在出现异常内存分配模式时发出警报 |
| 日期 | 事件 |
|---|
| 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 记录最后修改 |
| 资源 | 链接 |
|---|