Skip to content
KitploitKITPLOIT
도구블로그
제출
도구블로그
제출

해킹, 침투 테스트 및 사이버 보안 도구를 당신의 보안 무기고에!

Kitploit은 해킹, 사이버 보안 및 침투 테스트 도구 디렉토리입니다. 최신 프로젝트 업데이트를 발견하여 취약점을 찾고, 시스템을 분석하고, 테스트를 자동화하고, 보안을 강화하세요.

··피드·문의·개인정보·© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
CVE-2026-53360-POC — CVE-2026-53360에 대한 PoC: KVM SEV-SNP 페이지 상태 변경(PSC) 처리에서 게스트가 트리거하는 힙 out-of-bounds 읽기/쓰기 | Kitploit
도구/GitHubGitHub/0xcyberstan/cve-2026-53360-poc
Memory ForensicsVulnerability AnalysisExploitationHardware SecurityBinary Exploitation
GitHub0xcyberstan/cve-2026-53360-poc

CVE-2026-53360-POC

CVE-2026-53360에 대한 PoC: KVM SEV-SNP 페이지 상태 변경(PSC) 처리에서 게스트가 트리거하는 힙 out-of-bounds 읽기/쓰기

저장소 보기
11개월 전아직 검토되지 않음

인기

모두 보기 →

커뮤니티에서 가장 많이 사용되는 도구를 찾아보세요.

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

CVE-2026-53360: KVM SEV-SNP PSC 힙 버퍼 오버런

KVM의 SEV-SNP 페이지 상태 변경(PSC) 처리에서 발생하는 힙 읽기 및 쓰기 오버플로우에 대한 개념 증명입니다. 악의적인 SEV-SNP 게스트가 호스트 커널로 하여금 PSC 항목 배열을 슬랩 할당 영역 끝까지 탐색하게 만듭니다. 이로 인해 인접한 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 호스트 경로에만 해당. 일반 SEV-ES 게스트에 대해 KVM은 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)
    
  • SNP OVMF 펌웨어: https://github.com/AMDESE/AMDSEV/releases.

게스트:

  • SNP에서 부팅되는 모든 Linux 게스트. 모듈을 빌드하기 위해 build-essential과 linux-headers-$(uname -r)이 설치되어 있어야 합니다.

버그

SEV-SNP 게스트는 GHCB(4KB 공유 페이지)를 통해 호스트와 통신합니다. 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, 게스트가 제어 */

len은 게스트로부터 직접 오며, GFP_KERNEL_ACCOUNT는 cgroup-accounted 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로 설정하면 루프는 할당된 영역을 약 2KB 지나 인접한 슬랩 객체들을 탐색합니다.

프리미티브

범위를 벗어난 각 단계에서 다음 8바이트의 슬랩 메모리를 psc_entry로 재해석하여 PSC 코드를 통해 실행합니다. 이는 세 가지를 제공합니다:

  1. 읽기 오라클. 호스트는 인접한 qword를 디코딩하기 위해 읽어서, 버퍼가 소유하지 않았던 메모리에서 entry.gfn과 entry.operation을 추출합니다. KASAN이 잡는 슬랩 범위 초과 읽기입니다.
  2. 제한된 쓰기. 디코딩된 항목이 유효해 보이고 KVM_HC_MAP_GPA_RANGE로 전달되면, 완료 코드가 동일한 OOB 슬롯에 다시 씁니다: entries[idx].cur_page = entry.pagesize ? 512 : 1. 게스트가 선택한 워드의 하위 12비트에 두 개의 작은 값 중 하나가 기록되며, 반복 가능합니다.
  3. 실패 오라클. 항목이 유효성 검사를 통과하지 못하면, SW_EXITINFO2의 응답이 중단된 인덱스를 보고합니다. end_entry를 하나씩 증가시키면 인접 메모리가 no-op으로 디코딩되었는지, 아니면 실패한 것으로 디코딩되었는지 슬롯별로 누출되어, 객체 경계를 찾고 0과 0이 아닌 값을 구별하기에 충분합니다.

각 VMGEXIT는 스크래치 버퍼를 다시 할당하므로, 반복된 요청은 다른 freelist 슬롯에 배치되어 게스트가 하나에 고정되지 않고 이웃을 훑을 수 있습니다. 이를 종합하면 힙 레이아웃 공개, 위의 제한된 쓰기, 그리고 요청 간 use-after-free가 가능합니다.

PoC가 하는 일

trigger.c는 게스트 커널 모듈입니다. SEV-SNP 게스트 내에서 로드하면 단일 insmod로 호스트에 대해 네 단계를 실행합니다:

  • 1단계: 48개의 범위 초과 항목을 한 번에 하나씩 탐색하고 호스트 힙의 맵(인접 메모리의 0 vs 0이 아님)을 구축합니다.
  • 2단계: OOB 쓰기가 VMGEXIT 간에 지속됨을 증명하기 위해 cur_page를 0인 이웃에 쓰고, 이후 요청에서 이를 건너뛰는지 확인합니다.
  • 3단계: end_entry=200으로 하나의 요청을 보내고, 0이 아닌 데이터에 도달할 때까지 OOB 읽기가 얼마나 멀리 도달하는지 측정합니다.
  • 4단계: entries[3..10]이 범위를 벗어난 상태로 200개의 요청을 보내며, 각각 호스트에서 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개의 슬랩 범위 초과, 7개의 슬랩 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).

수정 사항

업스트림 수정은 GHCB v2 이상에서 GHCB 외부 스크래치 영역을 setup_vmgexit_scratch()에서 거부하여 버퍼를 고정된 알려진 크기로 고정시켜 루프가 끝을 넘어 실행되지 않도록 합니다:

root@kitploit:~
  } else {
+         /* GHCB v2 requires the scratch area to be within the GHCB. */
+         if (to_kvm_sev_info(svm->vcpu.kvm)->ghcb_version >= 2)
+                 goto e_scratch;
+
          /*
           * The guest memory must be read into a kernel buffer, so
           * limit the size

이 네 줄이 db3f219입니다. 이는 실제 버퍼 크기에 대해 항목 개수를 제한하고 READ_ONCE()를 통해 디스크립터를 다시 읽는 더 큰 시리즈의 일부로, 동일한 핸들러에서 버퍼 내 오프셋 변형과 time-of-check/time-of-use 레이스를 막습니다.

파일

파일설명
trigger.c네 가지 PoC 단계를 실행하는 게스트 커널 모듈
Makefile실행 중인 게스트 커널에 대해 trigger.ko를 빌드
LICENSEGPL-2.0, 모듈의 와 일치

문제 해결

  • 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 출력 없음: 호스트 cmdline에서 CONFIG_KASAN=y와 kasan_multi_shot를 확인하십시오.

경고

이것은 호스트 커널 힙 메모리를 손상시키고 KASAN을 트리거하며 호스트를 충돌시킬 수 있습니다. 자신이 제어하는 폐기 가능한 테스트 호스트와 소유한 VM에서만 실행하십시오. 공유 또는 프로덕션 인프라에서 실행하지 마십시오.

참고 자료

  • 분석: 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를 참조하십시오.

도구 다운로드
MODULE_LICENSE