Skip to content
KitploitKITPLOIT
ツールブログ
提出
ツールブログ
提出

ハッキング、侵入テスト、サイバーセキュリティツールをあなたのセキュリティアーセナルに!

Kitploitはハッキング、サイバーセキュリティ、ペネトレーションテストのツールディレクトリです。最新のプロジェクトアップデートを見つけて、脆弱性の発見、システム分析、テストの自動化、セキュリティの強化を行いましょう。

··フィード·お問い合わせ·プライバシー·© 2026 Kitploit

ツールディレクトリ

カテゴリ

すべてのカテゴリを見る
Loading categories
CVE-2026-53360-POC — CVE-2026-53360のPoC: KVM SEV-SNPのページ状態変更(PSC)処理におけるゲストトリガーのヒープ範囲外読み取り/書き込み | Kitploit
ツール/GitHubGitHub/0xcyberstan/cve-2026-53360-poc
メモリフォレンジック脆弱性分析エクスプロイトハードウェアセキュリティバイナリエクスプロイト
GitHub0xcyberstan/cve-2026-53360-poc

CVE-2026-53360-POC

CVE-2026-53360のPoC: KVM SEV-SNPのページ状態変更(PSC)処理におけるゲストトリガーのヒープ範囲外読み取り/書き込み

リポジトリを見る
11ヶ月前未レビュー

人気

すべて見る →

コミュニティで最も使われているツールを見つけましょう。

すべてのツールを探索

ツールコレクションを閲覧

すべてのツールを見る →
共有

CVE-2026-53360: KVM SEV-SNP PSC ヒープ領域外アクセス

KVMのSEV-SNP Page State Change(PSC)処理におけるヒープ領域外読み取りおよび書き込みの概念実証です。悪意のあるSEV-SNPゲストがホストカーネルにPSCエントリ配列をスラブ割り当ての末尾まで走査させます。これにより、隣接する kmalloc-cg-32 オブジェクトのレイアウトが漏洩し、制御された小さな値がそれらに書き込まれます。ゲストはこれを好きなだけ繰り返すことができます。

Full writeup: 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 (mainline, 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ゲストは利用できません。

ハードウェア:

  • AMD EPYCサーバーチップでSEV-SNP対応: 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ゲストは、4KBの共有ページであるGHCBを介してホストと通信します。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バイトの割り当てが得られます。これにはヘッダと2つのエントリが収まります。entries[1] 以降はすべて別のオブジェクトのメモリです。

そして snp_begin_psc() は、エントリ数を実際に割り当てたバッファではなく、プロトコル定数に対してチェックします:

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

if (idx_end >= VMGEXIT_PSC_MAX_COUNT) {   /* checks 253, NOT the buffer size */
        snp_complete_psc(svm, ...);
        return 1;
}

for (idx = idx_start; idx <= idx_end; idx++) {
        entry_start = entries[idx];       /* OOB once idx >= 2 */
        ...
}

24バイトのバッファでは2つのエントリしか存在しませんが、チェックでは end_entry を252まで許可します。これを252に設定すると、ループは割り当ての約2KB先、隣接するスラブオブジェクトをまたいで歩きます。

プリミティブ

末尾を超える各ステップでは、スラブメモリの次の8バイトを psc_entry として解釈し、PSCコードを通して処理します。これにより3つのことが得られます:

  1. 読み取りオラクル ホストは隣接するqwordを読み取ってデコードし、バッファが所有していないメモリから entry.gfn と entry.operation を引き出します。これがKASANが捕捉するスラブ領域外読み取りです。
  2. 制約付き書き込み デコードされたエントリが有効に見え、KVM_HC_MAP_GPA_RANGE としてディスパッチされた場合、完了コードが同じOOBスロットに書き戻します: entries[idx].cur_page = entry.pagesize ? 512 : 1。ゲストが選択したワードの下位12ビットに2つの小さな値のうちの1つを書き込み、繰り返し可能です。
  3. 失敗オラクル エントリが検証に失敗した場合、SW_EXITINFO2 の応答は停止したインデックスを報告します。end_entry を1つずつ増やすことで、スロットごとに隣接メモリがno-opとしてデコードされたか、失敗したものとしてデコードされたかが漏洩し、オブジェクトの境界を見つけ、ゼロと非ゼロを区別するのに十分です。

各VMGEXITはスクラッチバッファを再割り当てするため、繰り返しリクエストは異なるフリーリストスロットに配置され、ゲストは1つに固定されずに隣接オブジェクトをスイープできます。これらを組み合わせると、ヒープレイアウトの開示、上記の制約付き書き込み、およびリクエスト間でのuse-after-freeが得られます。

PoCの動作

trigger.c はゲストカーネルモジュールです。SEV-SNPゲスト内でロードすると、単一の insmod からホストに対して4つのステージを実行します:

  • ステージ1 48個の領域外エントリを1つずつプローブし、ホストヒープのマップ(ゼロ vs 非ゼロの隣接メモリ)を構築します。
  • ステージ2 ゼロの隣接領域に cur_page を書き込み、後のリクエストがそれをスキップすることを確認することで、OOB書き込みがVMGEXIT間で持続することを証明します。
  • ステージ3 end_entry=200 で1つのリクエストを発行し、非ゼロデータに到達するまで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をチェックし、それ以外の場所では実行を拒否します。4つのステージを実行し、自身をアンロードします(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件のスラブ解放後使用、4件の解放後使用)。すべて kmalloc-cg-32 に対するものです。テストホスト: AMD EPYC 7443P, Ubuntu 24.04.4, カーネル6.11.11 (KASAN有効), ゲストはAMDESE QEMU (snp-latest)。

修正

上流の修正では、setup_vmgexit_scratch() においてGHCB v2以降でGHCB外のスクラッチ領域を拒否し、バッファを固定の既知のサイズに固定するため、ループが末尾を超えて実行されることがなくなります:

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

それら4行が db3f219 です。これらは、エントリ数を実際のバッファサイズに対して制限し、記述子を READ_ONCE() で一度だけ読み直すという、より大きなシリーズの一部として導入されました。これにより、同じハンドラ内でのバッファ内オフセットの亜種と、チェック時刻/使用時刻の競合が修正されます。

ファイル

ファイル説明
trigger.c4つのPoCステージを実行するゲストカーネルモジュール
Makefile実行中のゲストカーネルに対して trigger.ko をビルド
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をトリガーし、ホストをクラッシュさせる可能性があります。自分が制御する使い捨てのテストホストで、自分が所有する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 を参照してください。

ツールをダウンロード
GPL-2.0, モジュールの MODULE_LICENSE に一致