系统:运行中
← 返回所有攻击
INFRASTRUCTURE CRITICAL NEW

llama.cpp 分布式推理 RPC 后端的未授权远程代码执行

llama.cpp RPC 后端缺失一处边界检查,任何能访问服务器端口的客户端都可读写进程内存并实现远程代码执行。已在 b8492 中修复。

2026-07-10 // 6 min affects: llama.cpp, ggml, ggml-rpc-server, distributed-inference

摘要 大多数 LLM 安全文章谈的是提示词,本文谈的是一个网络套接字。llama.cpp 提供了一个可选的 RPC 后端,用于将推理分摊到多台机器上。张量解析过程中缺失的一处边界检查,使任何能够访问 RPC 端口的客户端都能读写服务器内存,通过协议层的指针泄露绕过 ASLR,并实现远程代码执行——无需身份验证、无需提示词、无需用户交互。维护者公告(GHSA-j8rj-fmpv-wcxw)于 2026 年 3 月 26 日发布,修复包含在 b8492 构建中。项目文档早已提示不要将该服务暴露到网络上——这正是原因所在。

这是什么?

llama.cpp 是在本地运行开放权重模型的主流 C/C++ 引擎,GitHub 星标数远超 10 万。除单机使用外,它还提供分布式推理 RPC 后端:使用 -DGGML_RPC=ON 编译,在每台拥有 GPU 的主机上启动一个 ggml-rpc-server,主进程通过 TCP 将张量计算下发给它们。这就是把单机放不下的大模型分摊到多台机器运行的方式。

该缺陷是 RPC 服务器请求解析器中的一个内存安全漏洞。它于 2026 年 2 月上报给 CERT/CC,并于 2026 年 3 月 26 日以维护者安全公告的形式发布,评分为 CVSS 3.1 9.8(严重),归类为 CWE-119(对内存缓冲区边界内操作的限制不当)。它影响 b8492 之前的所有构建,该版本已修复此问题。

工作原理

RPC 服务器在执行计算图时,会通过一个辅助函数根据网络接收到的字节重建每个张量。该函数仅在张量的 buffer 字段非零时才校验攻击者提供的 data 指针。将 buffer 置为 0,边界检查便被完全跳过,而 data 指针仍会直接取自请求并交给计算内核:

// 简化:buffer = 0 -> nullptr,因此下面的校验块永远不会执行
result->buffer = reinterpret_cast<ggml_backend_buffer_t>(tensor->buffer);
if (result->buffer) {
    // 对 result->data 的边界 / 合理性检查仅存在于此块内
}
result->data = reinterpret_cast<void *>(tensor->data); // 无条件取自请求

仅这一处缺口就赋予攻击者对服务器进程的任意读写原语。由于客户端分配缓冲区时 RPC 协议还会返回原始内存地址,攻击者无需猜测任何位置:指针泄露绕过了 ASLR,而缓冲区内部结构中的一个函数指针可被覆写,从而将后续请求重定向到攻击者控制的内存操作。我们刻意省略可运行的完整利用链——这里关注的是漏洞类别,而非可直接照搬的武器。上报者的完整分析与公告中包含供防御方所需的复现细节。

有两点让此漏洞由理论变为现实。第一,不存在任何身份验证——协议本身不提供,因此“可达即沦陷”。第二,同样的根因曾导致 2024 年在这个函数中修复过的两处越界读取漏洞;那些补丁加固了张量读取与写入命令,但计算图执行命令走的是另一条从未被覆盖的代码路径。该底层弱点自 2024 年 5 月 RPC 后端首次合入起便一直存在。

示例提示

下面的代码片段展示了根本原因:当 buffer0 时,RPC 张量解析器会跳过边界检查,使攻击者控制的 data 指针直接进入计算内核。此处不展示可用的漏洞利用——仅供防御者参考。

# llama.cpp RPC graph-compute RCE (illustrative, defensive)
# The tensor parser only bounds-checks data when buffer != 0:
if tensor.buffer:              # attacker sets buffer = 0 to skip this
    validate(tensor.data)      # [bounds check lives only here]
result.data = tensor.data      # [payload] taken from the wire unconditionally
# Root cause: reachability == compromise; the RPC protocol has no auth.
# Defense: upgrade to build b8492+, bind ggml-rpc-server to 127.0.0.1,
# never publish port 50052, and tunnel nodes over mTLS/WireGuard.

为何重要

推理节点是高价值目标。它持有模型权重、处理中的提示词,往往还有 API 密钥,并且通常位于对内网具有广泛可达性的 GPU 主机上。在 RPC 服务器上执行代码,可能意味着在集群内横向移动、窃取机密与模型,或仅仅是被劫持的 GPU。默认监听端口(50052)易于指纹识别,而该后端存在的意义本身——跨机器推理——正把运维者推向恰恰会将其变成远程代码执行的网络暴露。发布该端口或监听 0.0.0.0 的 Docker 部署可被直接访问,且常以 root 身份运行。

防御措施

  • 升级到 b8492 或更高构建(修复见 PR #20908),它恢复了计算图执行路径上的边界校验。
  • 切勿将 RPC 端口暴露到不受信任的网络。 项目的 RPC README 说得很明确:该后端是概念验证,“脆弱且不安全”,绝不应在开放网络上运行。请把它当作仅限可信 LAN 的服务。
  • 监听 127.0.0.1 并使用隧道。 若确需跨主机推理,请让每个 ggml-rpc-server 保持在本地回环,并通过双向认证的叠加网络(WireGuard、mTLS 隧道、私有 VPC)连接各节点,而非在可路由接口上使用裸 TCP。
  • 不要以 --network=host 运行推理容器, 也绝不要把 50052 发布到互联网。仅在身份验证之后暴露预期的 HTTP API。
  • 分段与监控。 将 GPU 推理节点置于隔离的网络区域;对指向 RPC 端口的异常连接以及推理进程派生 shell 的行为进行告警。
  • 主动排查暴露面。 扫描自有网段中可达的 RPC 端口,确认无任何端口从可信边界之外响应。

状态

项目详情
参考CVE-2026-34159 · GHSA-j8rj-fmpv-wcxw · CWE-119
受影响llama.cpp RPC 后端,b8492 之前的构建
严重性CVSS 3.1 9.8(严重)——网络、未授权、无需交互
上报CERT/CC,2026 年 2 月 8 日(VU#748698)
公告2026 年 3 月 26 日发布
修复b8492 构建(PR #20908)
相关历史同一函数,2024 年两处越界读取修复(CVE-2024-42478 / CVE-2024-42479)
备注RPC 后端在文档中被标注为不安全,且不在项目漏洞范围之内

Sources