Skip to content
KitploitKITPLOIT
工具博客
提交
工具博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

··订阅源·联系·隐私·© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
CVE-2026-53360-POC — PoC for CVE-2026-53360: guest-triggered heap out-of-bounds read/write in KVM SEV-SNP Page State Change (PSC) handling. | Kitploit
工具/GitHubGitHub/0xcyberstan/cve-2026-53360-poc
内存取证漏洞分析漏洞利用硬件安全二进制利用
GitHub0xcyberstan/cve-2026-53360-poc

CVE-2026-53360-POC

PoC for CVE-2026-53360: guest-triggered heap out-of-bounds read/write in KVM SEV-SNP Page State Change (PSC) handling.

查看仓库
132个月前尚未审核

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享

CVE-2026-53360: KVM SEV-SNP PSC 堆越界

KVM 中 SEV-SNP 页面状态变更 (PSC) 处理的一个堆越界读取和写入概念验证。恶意 SEV-SNP 客户机使主机内核遍历 PSC 条目数组超出其 slab 分配末端。这会泄露相邻 kmalloc-cg-32 对象的布局,并向其中写入受控的小值,且客户机可以任意重复此操作。

完整文章:https://cyberstan.co.uk/sev-snp-oob/

CVECVE-2026-53360
组件KVM SNP 主机支持,arch/x86/kvm/svm/sev.c
引入9b54e248d264 (首次 KVM SNP PSC 处理,2024年5月,~v6.10)
修复db3f219 (主线,2026年5月,Cc: stable),标记为 Fixes: 4af663c
报告[email protected],2026年4月8日
影响仅 SEV-SNP 主机路径。KVM 不启用普通 SEV-ES 客户机的 PSC。

影响

任意 SEV-SNP 客户机可以通过发送畸形的 PSC 请求破坏主机内核堆并回读其布局信息。这是从客户机到主机的方向:SEV-SNP 旨在保护客户机免受不可信主机的攻击,但主机仍然需要防御恶意客户机,而这个处理程序没有做到。

要求

需要真实的 SEV-SNP 硬件。无法在 Intel 上复现,嵌套虚拟化也无法提供 SNP 客户机。

硬件:

  • 支持 SEV-SNP 的 AMD EPYC 服务器芯片:Milan (7003) 或更新,即 Genoa (9004)、Bergamo、Siena 或 Turin。SEV-SNP 是 EPYC 专用的硅特性。Ryzen 或 Threadripper 上没有,Intel 也没有对应的等效特性(Intel 使用 TDX)。
  • 裸金属。裸金属云实例也可以(Vultr、AWS *.metal、Hetzner AX 等)。
  • 在 BIOS 中启用 SEV、SEV-ES、SEV-SNP、SME、IOMMU 和 SVM。托管裸金属云通常已开启这些选项。

主机内核:

  • 使用 KASAN 构建,以便报告越界访问。没有 KASAN 时,漏洞仍然会破坏主机内存,只是不会打印。在 6.11.11 上测试过。
    root@kitploit:~
    CONFIG_KASAN=y
    CONFIG_KASAN_GENERIC=y
    CONFIG_KVM=y
    CONFIG_KVM_AMD=y
    CONFIG_KVM_AMD_SEV=y
    CONFIG_CRYPTO_DEV_SP_PSP=y
    
  • 以 SNP 启用状态启动,并将 KASAN 设为多击模式,以便记录每次命中:
    root@kitploit:~
    kvm_amd.sev=1 kvm_amd.sev_es=1 kvm_amd.sev_snp=1 kasan_multi_shot
    
  • 确认主机已就绪:
    root@kitploit:~
    cat /sys/module/kvm_amd/parameters/sev_snp     # Y
    ls /dev/sev                                     # /dev/sev
    

主机用户空间:

  • 支持 SNP 的 QEMU。标准 QEMU 不支持 SNP,因此构建 AMD 分支:
    root@kitploit:~
    git clone https://github.com/AMDESE/qemu.git
    cd qemu && git checkout snp-latest
    mkdir build && cd build
    ../configure --target-list=x86_64-softmmu && make -j$(nproc)
    
  • 来自 https://github.com/AMDESE/AMDSEV/releases 的 SNP OVMF 固件。

客户机:

  • 任何在 SNP 下启动的 Linux 客户机,已安装 build-essential 和 linux-headers-$(uname -r),以便在其中构建模块。

漏洞

SEV-SNP 客户机通过 GHCB(一个 4 KB 共享页面)与主机通信。PSC 请求将 SW_EXITCODE 设置为 SVM_VMGEXIT_PSC (0x80000010),将 SW_SCRATCH 指向一个描述符,并将描述符长度放入 SW_EXITINFO2。

描述符是一个 struct psc_buffer:一个 8 字节头部后跟一个 8 字节条目数组。没有明确的数量字段。主机从 hdr->cur_entry 到 hdr->end_entry 处理条目,两者均由客户机控制。

root@kitploit:~
struct psc_hdr {
        u16 cur_entry;
        u16 end_entry;
        u32 reserved;
} __packed;                     /* 8 bytes */

struct psc_entry {
        u64 cur_page    : 12;
        u64 gfn         : 40;
        u64 operation   :  4;
        u64 pagesize    :  1;
        u64 reserved    :  7;
} __packed;                     /* 8 bytes */

GHCB v2+ 客户机应将其暂存区域保持在 GHCB 的 2032 字节共享缓冲区内部,以便主机可以重用其现有映射。(2032 - 8) / 8 = 253 个条目适合那里,这就是协议最大值 VMGEXIT_PSC_MAX_COUNT (253) 的来源。这个数字仅在缓冲区确实是共享缓冲区时才有意义。

如果客户机将暂存区域指向 GHCB 外部,主机无法使用其映射,因此 setup_vmgexit_scratch() 会分配一个单独缓冲区,大小由客户机请求决定。SNP 绝不应该走这条路径,但没有任何东西阻止它:

root@kitploit:~
scratch_va = kvzalloc(len, GFP_KERNEL_ACCOUNT);   /* len == exit_info_2, guest-controlled */

len 直接来自客户机,GFP_KERNEL_ACCOUNT 将分配放入 cgroup 记账的 kmalloc-cg-N 缓存。请求 exit_info_2 = 24,你将获得 32 字节 kmalloc-cg-32 槽中的一个 24 字节分配:头部加上两个条目的空间。entries[1] 之后的所有内容都是另一个对象的内存。

然后 snp_begin_psc() 检查条目计数是否超过协议常量,而不是针对它实际分配的缓冲区:

root@kitploit:~
idx_end = hdr->end_entry;

if (idx_end >= VMGEXIT_PSC_MAX_COUNT) {   /* 检查 253,而非缓冲区大小 */
        snp_complete_psc(svm, ...);
        return 1;
}

for (idx = idx_start; idx <= idx_end; idx++) {
        entry_start = entries[idx];       /* 一旦 idx >= 2 就越界 */
        ...
}

对于只有两个条目的 24 字节缓冲区,检查却允许 end_entry 高达 252。将其设置为 252,循环将遍历分配之外约 2 KB,跨越相邻的 slab 对象。

原语

超出末端的每一步都将 slab 内存的下 8 个字节重新解释为 psc_entry,并通过 PSC 代码处理。这提供了三种能力:

  1. 读取 oracle。主机读取相邻的 qword 仅仅是为了解码它,从缓冲区从未拥有的内存中提取 entry.gfn 和 entry.operation。这是 KASAN 捕获的 slab 越界读取。
  2. 受限写入。如果解码后的条目看起来有效并被分派为 KVM_HC_MAP_GPA_RANGE,完成代码会写回相同的越界槽:entries[idx].cur_page = entry.pagesize ? 512 : 1。两个小值之一写入客户机选择的字的低 12 位,可重复。
  3. 失败 oracle。如果条目未通过验证,SW_EXITINFO2 中的响应会报告停止处的索引。一次只增加一个 end_entry,逐槽泄露相邻内存解码为无操作还是失败,这足以找到对象边界并区分零和非零。

每次 VMGEXIT 都会重新分配暂存缓冲区,因此重复请求会落在不同的空闲列表槽中,让客户机扫描相邻区域而不是卡在一个位置。综合起来,这实现了堆布局泄露、上述受限写入以及跨请求的释放后使用。

PoC 的功能

trigger.c 是一个客户机内核模块。在 SEV-SNP 客户机内部加载它,它会在单个 insmod 中驱动四个阶段来攻击主机:

  • 阶段 1 每次探测 48 个越界条目,并构建主机堆的映射(相邻内存的零 vs 非零)。
  • 阶段 2 通过将 cur_page 写入零相邻区域并确认稍后的请求跳过它,证明越界写入在 VMGEXIT 之间持续存在。
  • 阶段 3 发起一个 end_entry=200 的请求,并测量越界读取在遇到非零数据之前到达多远。
  • 阶段 4 发起 200 个请求,其中 entries[3..10] 越界,每个请求都会在主机关触发 KASAN 报告。

模块分配一个页面,使用 set_memory_decrypted() 将其标记为解密,用作暂存区域,并手动构建 GHCB PSC 请求。它以 -EAGAIN 退出,因此不会保持加载状态。

构建和运行

1. 启动一个 SNP 客户机

根据你的设置调整 OVMF 和磁盘路径:

root@kitploit:~
qemu-system-x86_64 \
    -enable-kvm -cpu EPYC-v4 \
    -machine q35,confidential-guest-support=sev0,memory-backend=ram1 \
    -object memory-backend-memfd,id=ram1,size=4G \
    -object sev-snp-guest,id=sev0,cbitpos=51,reduced-phys-bits=1,policy=0x30000 \
    -smp 4 -m 4G \
    -bios OVMF_SNP.fd \
    -drive file=guest.qcow2,format=qcow2,if=virtio \
    -netdev user,id=net0,hostfwd=tcp::2222-:22 \
    -device virtio-net-pci,netdev=net0 \
    -nographic

2. 在客户机中构建并加载

将 trigger.c 和 Makefile 复制到客户机中,然后:

root@kitploit:~
make
insmod trigger.ko

模块首先通过 CPUID 检查 SEV-SNP,拒绝在其他任何地方运行。它执行四个阶段并自行卸载(init 返回 -EAGAIN,因此它永远不会驻留)。

3. 观察主机

在主机上:

root@kitploit:~
dmesg | grep -E "KASAN|BUG|snp_begin_psc"

预期输出:

root@kitploit:~
BUG: KASAN: slab-out-of-bounds in snp_begin_psc+0x126/0x890
Read of size 8 at addr ffff888219ffb5e0 by task qemu-system-x86/2199

BUG: KASAN: slab-out-of-bounds in snp_begin_psc+0x468/0x890
Write of size 8 at addr ffff888351566648 by task qemu-system-x86/2199

The buggy address belongs to the object at ffff888XXXXXXXXX
 which belongs to the cache kmalloc-cg-32 of size 32

单个 insmod 在测试主机上产生了 73 个 KASAN 报告(62 个 slab-out-of-bounds,7 个 slab-use-after-free,4 个 use-after-free),全部针对 kmalloc-cg-32。测试主机:AMD EPYC 7443P,Ubuntu 24.04.4,内核 6.11.11 带 KASAN,客户机使用 AMDESE QEMU(snp-latest)。

修复

上游修复在 setup_vmgexit_scratch() 中拒绝任何超出 GHCB 的暂存区域(针对 GHCB v2 及更高版本),这将缓冲区固定为固定已知大小,从而循环永远不会跑出末端:

root@kitploit:~
  } else {
+         /* GHCB v2 要求暂存区域位于 GHCB 内部。 */
+         if (to_kvm_sev_info(svm->vcpu.kvm)->ghcb_version >= 2)
+                 goto e_scratch;
+
          /*
           * 客户机内存必须读入内核缓冲区,因此
           * 限制大小

这四行是 db3f219。它们作为一个更大系列的一部分落地,该系列还根据实际缓冲区大小限制条目计数,并通过 READ_ONCE() 重新读取描述符,关闭了同一处理程序中的偏移到缓冲区变体和检查时间/使用时间竞争。

文件

文件描述
trigger.c驱动四个 PoC 阶段的客户机内核模块
Makefile针对运行中的客户机内核构建 trigger.ko
LICENSEGPL-2.0,与模块的 MODULE_LICENSE 一致

故障排除

  • not an SEV-SNP guest:QEMU 未使用 sev-snp-guest 启动,或主机 SNP 已关闭。
  • QEMU SEV-SNP not supported:检查 /sys/module/kvm_amd/parameters/sev_snp、BIOS 设置和启动参数。
  • QEMU LAUNCH_START failed:PSP 未初始化。检查 dmesg | grep psp 和 CONFIG_CRYPTO_DEV_SP_PSP=y。
  • 无 KASAN 输出:验证主机命令行上是否设置了 CONFIG_KASAN=y 和 kasan_multi_shot。

警告

这会破坏主机内核堆内存,触发 KASAN,并可能使主机崩溃。只在你控制的、一次性测试主机上运行,且仅在你拥有的虚拟机内部。不要在共享或生产基础设施上运行。

参考

  • 文章:https://cyberstan.co.uk/sev-snp-oob/
  • CVE-2026-53360(在 linux-cve-announce 上跟踪提交 db3f219)
  • 修复:db3f219,作者 Mike Roth,审查者 Tom Lendacky,提交者 Paolo Bonzini
  • 引入:9b54e248d264;修复标记为 Fixes: 4af663c
  • GHCB 规范,第 2.1 节(SW_SCRATCH 必须在 GHCB 共享缓冲区内部)

许可证

trigger.c 是 GPL-2.0,与其 MODULE_LICENSE 一致。参见 LICENSE。

下载工具