这次验证没有弹 shell,没有执行任何宿主命令,只让宿主上的 Firecracker 进程往自己的标准错误流写了 8 个字节。
安全研究机构 PWN.AI 公布的 PoC 运行记录里,shellAttempted 与 hostCommandAttempted 两个字段都是 false,验证停留在「控制权已经拿到」这一步。
2026 年 11 月,研究员 Paulos Yibelo 公布了 PwnEscape 系列研究的第二部分成果。
测试代码从客户机内部逆向解析宿主内存,成功在宿主终端的标准错误流输出了 8 字节测试标记,全程未触碰宿主硬盘文件或派生后门。
许多云原生架构师习惯将微虚拟机视为天然坚固的硬核隔离层。 这项研究展示了相反的工程事实:Firecracker 的安全隔离重心始终落在外层 jailer 施加的权限与命名空间封装上,微虚拟机自身并不具备抗衡宿主内核缺陷的独立防御能力。 在以 root 身份运行且未启用 jailer 的调试姿态下,一个宿主内核缺陷足以让攻击者穿透虚拟化边界,直接掌握宿主代码执行权。
8字节写入收工:只验执行权限不留后门
在常规攻防演示中,攻击者拿到权限往往会弹出一个宿主 root shell,或者修改系统文件以展示破坏力。
Paulos Yibelo 在这次验证中采取了克制策略。
测试载荷仅通过系统调用 write(2, "N8V23M2\n", 8) 向宿主 stderr 写入 8 个字节,写完即走,立即清理现场。
执行完成后,宿主 stderr 准时捕获到了这 8 字节标记。
宿主上的 Firecracker 进程 PID 2936 依然健康运行,未产生任何崩溃退出。
客户机持续运行了 1615.72 秒,外部网络与 SSH 连接全程通畅,宿主内核日志 dmesg 也没有出现任何报错。
这种精准保护展现出对虚拟化调度的深度掌控,证明逃逸并非偶发的内存踩踏,而是可控的执行流重定向。
载荷执行完毕后,执行流通过 xor eax, eax; ret 顺畅清空返回值。
先前被覆盖的 3 个栈字也得到了精确恢复,宿主内存中的代码段与动态链接库未受篡改。
研究团队用这种严密的验证,把注意力拉回虚拟化边界本身的隔离能力上。
裸奔环境暴露破口:root无Jailer放大内核缺陷
这次逃逸实验设立了一组极具参考价值的测试基线。
宿主系统采用 7.0.0-1011-aws 内核,客户机运行 6.18.44+ 内核,测试目标为官方发布的 Firecracker v1.16.1 编译版本。
关键变量在于启动方式:宿主通过 systemd-run 以 root 权限启动进程,并用 taskset 绑定 CPU,全程没有挂载官方安全套件 jailer。
这种配置常见于开发调试与性能测试环境,许多工程师为了排查网络或磁盘性能瓶颈,常常会临时移除 jailer。 作者明确说明,剥离 jailer 是为了单独衡量微虚拟机本身的防御能力。 逃逸依赖的前置条件是编号为 CVE-2026-99999 的宿主内核缺陷,该漏洞存在于 IPv4 校验和逻辑中,能在宿主侧提供任意内存读写原语。
当微虚拟机以 root 身份裸奔时,局部内存缺陷获得了直通宿主的放大通道。 微虚拟机此时失去了 cgroups 资源限制,没有 chroot 根目录切换,seccomp 系统调用过滤同样缺位。 失去了多重防御纵深,微虚拟机进程直接暴露出原本由外层防线遮蔽的攻击面。
微虚拟机的轻量化设计原本是为了消减攻击面,它移除了传统 QEMU 中繁杂的虚拟设备驱动,只保留核心的 virtio 总线。 然而精简并不等同于免疫。 当宿主内核本身失守时,微虚拟机的进程边界随之松动,未设防的宿主环境直接将 root 执行权拱手相让。
内存反向巡航:从Guest随机数逆推宿主CR3根
「客户机内部没有哪怕一字节的宿主内存。」 这是 Paulos Yibelo 在规划攻击路径时必须面对的硬件现实。 现代硬件虚拟化通过二阶地址转换隔开了两套物理内存,站在虚拟机内部无法直接窥探宿主的内存分布。
图:nonce 在宿主内存中定位 guest 页,反向遍历宿主页表找到 CR3 根,再定位并校验 Firecracker 可执行镜像。来源:PWN.AI Security Research
攻破这道隔离的第一步是投放灯塔。
研究者在客户机内存页中写入一个唯一的 64 位随机标记(nonce),随后借助内核读写原语在宿主物理内存中展开搜索。
一旦定位到匹配该随机标记的物理页帧,便确立了客户机页面在宿主中的基址 guest_page_hpa,内存搜索由此演进为坐标换算。
拿到物理页基址后,攻击者利用页表反向映射算法展开递归。
程序一步步倒推回宿主内核的顶级页全局目录 host_pgd,即 CR3 寄存器指向的地址根节点。
随后算法扫描宿主内存,识别出 Firecracker 的 ELF 镜像,并用其中一段已知字节序列确认身份,再据此推算 ASLR 加载偏移。
偏移一旦确定,firecracker_base 就把 ELF 里的符号地址换算成进程运行时的真实地址,内存原语从「读物理内存」升级成「按符号读进程」。
写入之前,攻击者会先验证三处代码:输出标记用的 write(2) 包装函数、KVM ioctl 之后的下一条指令、以及用来清空返回值的 xor eax,eax; ret 序列。
任何一处对不上就放弃该候选地址,避免向错误位置写内存把宿主打崩。
严苛筛选KVM帧:三重交叉校验锁定调度上下文
摸清宿主进程与页表布局只是拿到了系统地图,控制权转移发生在硬件调度交替的瞬间。
Firecracker 的虚拟 CPU 线程在宿主用户态循环调用 ioctl(vcpu_fd, KVM_RUN, ...) 进入虚拟化运行状态。
当客户机发生 I/O 操作或主动出让时,CPU 会退出虚拟化模式,将控制权交还给宿主,并在内核栈上保存上下文结构 pt_regs。
图:guest 定位宿主上的 Firecracker 进程、找到 vCPU 线程保存的寄存器状态、并重定向 KVM 返回路径的三段式链条。来源:PWN.AI Security Research
在庞大的宿主内核栈空间中寻找活跃的 vCPU 寄存器帧,容不得半点猜测。 任何一次向错误指针写入载荷的动作,都会直接导致宿主内核崩溃。 研究者设立了严苛的交叉验证规则,只有同时满足所有特征的内存块才会被判定为目标寄存器帧。
图:候选寄存器帧必须同时满足 KVM ioctl 身份、恢复出的进程页表翻译和已校验的 Firecracker 代码映射三重条件。来源:PWN.AI Security Research
这些校验条件形成了一套精密矩阵。
系统调用号 rax 必须准确为 16(对应 ioctl),调用请求参数精确等于 KVM_RUN,且文件描述符 rdi 落在已知范围。
栈上保存的 RIP 偏移必须位于 ioctl 附近,RSP 能通过宿主页表进行双向虚拟地址翻译,段选择子数值合规,且返回地址落在已校验的代码段内。
这套多维特征约束有效排除了内存噪音的干扰。 它让寄存器帧定位的误判率降为零,为接下来的精确执行铺平了道路。
串行单字节触发:安全防线必须前置到Jailer
锁定 vCPU 线程的寄存器状态后,攻击链条迎来了收拢。
载荷代码没有采用外部进程注入,而是直接复用 Firecracker 进程已有的 write 系统调用封装函数。
攻击脚本修改栈上保存的 RIP、RDI、RSI 和 RDX 寄存器,将文件描述符指向 stderr,缓冲区指向栈上的 8 字节标记。
激活机制非常轻巧,不需要复杂的网络封包交互。
攻击者在客户机内仅向串行接口写入一位字符,立即促使 KVM 退出虚拟机状态并返回宿主。
宿主线程恢复执行的瞬间,被篡改的返回指针带着预设参数直接切入 write 逻辑,8 个字符在标准错误终端如期打印。
一次普通的单字节串行 I/O 动作,被巧妙转化为引爆宿主代码执行的开关。
整个利用过程给出了清晰的工程结论:微虚拟机带来的轻量化设计,并不能替代操作系统层面的纵深防御。 Firecracker 大幅裁撤了设备驱动,有效收缩了传统虚拟化的攻击面。 然而面对宿主内核缺陷,剥离了 jailer 的微虚拟机在 root 环境下缺乏退路。 安全防线的基石始终在于外层 jailer 强制执行的独立用户命名空间、chroot 沙盒以及受限的 seccomp 规则,放弃外部加固等于将信任押注在宿主内核零缺陷的假设之上。
参考链接:
- PWN.AI 安全研究博客
- Firecracker 官方安全模型与隔离规范