返回资讯中心
外部精选
软件工程
#开发者实时流

Coinspect 演示从访客用户空间逃逸 Firecracker 沙箱

来源标题:Escaping Firecracker from Guest Userspace

安全公司 Coinspect 演示了从访客用户空间逃逸 Firecracker 沙箱的攻击链,分两个阶段实现 guest-to-Firecracker 突破。该问题已在 Firecracker v1.16.2 和 v1.17.0 修复,AWS 表示包括 Lambda 在内的自家服务不受影响、客户无需操作。

Hacker News 最新achille2026/11/5 · 昨天27 分钟阅读

以下正文由 AI 翻译自 Hacker News 最新(原文版权归原站所有),可能存在偏差,重要内容请以原文为准。

Firecracker 以云规模在轻量级虚拟机中运行不受信任的工作负载。每一台这样的机器(即 microVM)都是一个 guest:一个沙箱,旨在将其中的程序与宿主机(运行 Firecracker 的底层服务器)隔离开来。

Coinspect 演示了从 guest 用户空间发起的 Firecracker 沙箱逃逸。我们的利用链分为两个阶段:

guest 到 Firecracker 的问题已在 Firecracker v1.16.2 和 v1.17.0 中修复。GitHub 安全公告和 AWS 安全公告提供了官方指引。FC-03 提出的 seccomp 重新设计方案正在 PR #6287 中接受审查;AWS 不计划为其单独分配 CVE。受影响版本及修复情况见“修复状态”。

Firecracker 是以安全为核心的主要沙箱平台之一。其设计结合了硬件虚拟化、刻意缩小的面向 guest 的攻击面以及多层隔离 containment。它为 AWS Lambda 和 Fargate 提供支撑;AWS 在 2026 年报告称,Firecracker 每月支持超过 15 万亿次 Lambda 调用。

AWS 在其安全公告中声明,包括 AWS Lambda 在内的 AWS 服务不受此问题影响,这些服务的客户无需采取任何行动。

对于如此大规模使用的平台而言,Firecracker 的公开公告记录很短:截至 2026 年 10 月 21 日,其 GitHub 安全公告页面仅列出两条已发布的公告。

Firecracker 还被用于在 Amazon Bedrock AgentCore、DigitalOcean Managed Agents、Vercel Sandbox 和 E2B 中运行或隔离 AI agent 及其代码。Vercel 将其 Firecracker microVM 认定为沙箱的计算安全边界。随着 agent 获得执行代码的能力,这种隔离的强度变得更加重要。我们的研究针对 Firecracker 本身;我们未评估上述服务的部署情况。

我们测试的边界是 Firecracker 的根本所在:guest 内的 root 仍然应当被限制在该 guest 内。Firecracker 假定甚至 guest 内核也可能是恶意的。我们的 guest 用户空间概念验证需要 root 权限,但无需在 guest 内核中运行任何代码。

受影响的配置涉及从使用 File 内存后端的快照恢复的 VM,外加一个允许 guest 请求内存丢弃的 balloon 或 virtio-mem 设备。File 后端将快照的 RAM 文件以私有映射方式映射到 Firecracker 进程中。

Firecracker 的宿主机侧进程是虚拟机监视器(VMM)。图 1 展示了 guest 如何到达 VMM,以及在那里运行的代码如何进而到达 Firecracker 策略所阻止的宿主机操作。

图 1. guest 到 Firecracker 的逃逸使 guest 能够访问活跃的 VMM 内存,并获得一条代码执行路径;FC-03 让该代码能够执行 Firecracker 策略所阻止的宿主机操作。

我们的概念验证使用了 Full 快照和传统的 virtio-balloon 设备来到达 Firecracker 的内存丢弃路径。

为了丢弃快照支撑的页面,受影响的 Firecracker 版本会尝试在同一地址用匿名内存(不再由快照文件支撑的新页面)替换其宿主机映射。这使用了 MAP_FIXED:旧映射可以在新映射建立之前被移除。危险的情况是在移除之后发生失败;若失败后旧映射保持完好,则不会产生这种所有权问题。balloon 处理程序在尝试丢弃之前,先将 guest 的 balloon 丢弃请求标记为已使用;如果丢弃失败,它会记录错误并继续。

在我们的概念验证中,guest 产生的内存压力消耗了预先配置的每 microVM 内存限制所允许的余量——这一资源控制与 Firecracker 的生产指引一致——并导致了那次延迟失败。

受影响的内存丢弃代码尝试了下面的替换操作(展示了失败路径):

let ret = unsafe { libc::mmap( phys_address.cast(), len, libc::PROT_READ | libc::PROT_WRITE, libc::MAP_FIXED | libc::MAP_ANONYMOUS | libc::MAP_PRIVATE, -1, 0, ) }; if ret == libc::MAP_FAILED { let os_error = std::io::Error::last_os_error(); error!("discard_range: mmap failed: {:?}", os_error); Err(GuestMemoryError::IOError(os_error))

balloon 处理程序在调用 discard_range 之前将 balloon 丢弃请求标记为已使用,并在失败时记录错误:

queue.add_used(head.index, 0)?; // ... prepare the page ranges ... if let Err(err) = mem.discard_range( guest_addr, usize::try_from(range_len).unwrap() << VIRTIO_BALLOON_PFN_SHIFT, ) { error!("Error removing memory range: {:?}", err);

从替换失败到 VMM 访问

KVM 是宿主机的虚拟化组件,它维护一个将 guest 内存范围链接到宿主机地址的内存槽。延迟失败移除了 guest RAM 映射,但使该内存槽保持活跃:KVM 仍将该地址视为 guest 内存。当 Firecracker 后来将该地址复用于自身数据时,guest 便可以读取和修改活跃的 VMM 分配。KVM 跟踪的是地址,而非其新所有者。

图 2. 在替换失败并发生地址复用后,仍然活跃的 KVM 内存槽将 guest 访问导向 Firecracker 内存。

FC-03 要求代码已经在 VMM 线程中执行,无论是通过 guest 到 Firecracker 的逃逸还是其他途径。在我们的利用链中,逃逸在 Firecracker 的 EventManager(VMM 负责设备工作的主事件循环)中提供了这种执行能力。FC-03 让该代码能够使用宿主机的 io_uring 接口,该接口通过共享队列向宿主机内核提交操作。

Firecracker 使用 seccomp 过滤其 VMM 线程向宿主机内核发起的系统调用。然而,受影响的 VMM seccomp 策略允许了 io_uring 的设置、注册和提交系统调用:

{ "syscall": "io_uring_setup" }, { "syscall": "io_uring_register" }, { "syscall": "io_uring_enter" }

当 Firecracker 为异步 I/O 创建 io_uring ring 时,它先以禁用状态启动该 ring,注册允许的操作和文件描述符,然后启用它。这些限制仅适用于该特定 ring;新的 ring 不会继承它们。Firecracker 的 ring 设置代码展示了这一顺序。

(原文较长,此处译出前 6000 字,完整内容请点「打开原文」。)

正文由 探How 从来源站点 RSS 同步,内容未经改写;遇到排版缺失或需要图片、视频时请以原文为准。

打开原文
去社区讨论 →