
VirtualBox 7.2.20 - 高 - ローカル - ヒープオーバーフロー - HGCM SSM cParms ラップ
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · vbox-hgcm-ssm-cparms
クラス: ヒープオーバーフロー 到達範囲: ローカル (ホスト)
Oracle VM VirtualBox OSS 7.2.20 (f2792cf44) - Oracle
ライブの HGCM は依然として cParms > 32 を拒否する。保存状態のロードは拒否しない。vmmdevR3HgcmLoadState は .sav から cParms を読み取る際に VMMDEV_MAX_HGCM_PARMS の上限を適用せず、その後 uint32_t cbCmd でコマンドのサイズを計算する。cParms = 0x4000000 の場合、この積は sizeof(VBOXHGCMCMD) (約120) にラップアラウンドする。最初の enmType ストアはすでにブロックを越えた4バイトの書き込みとなる。
悪意ある保存状態を復元するホストユーザーは、VM プロセスのヒープをオーバーフローさせる。ゲストは保存を通じてこれを仕込むことはできない。
| ID | CVE 未割り当て |
| クラス | ヒープオーバーフロー (VM プロセスの範囲外書き込み。ホストカーネルエスケープではない) |
| 到達範囲 | ローカル (ホスト) (UI:R 保存状態 / スナップショットの復元) |
| CWE | CWE-190, CWE-787 |
| CVSS | High: 7.8 CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H |
| 製品 | VirtualBox OSS |
| 影響を受けるバージョン | 7.2.20 (f2792cf44f663989818507e36d3db5f978523c5e) |
| 認証 | ホストユーザーが保存済み VM、スナップショット、または .sav を復元する |
| ライセンス | GNU Affero GPL v3.0 |
| ラボ | 127.0.0.1 のみ。ソースハーネス。VirtualBox の起動なし、.sav のパースなし。 |
保留中の VMMDev HGCM CALL を含む保存状態を持つ VM フォルダーをオペレーターに渡す。オペレーターが保存済み VM の Start をクリックするか、スナップショットを復元するか、.sav を取り込む。コンソールの復元は SSMR3 を経由して vmmdevR3LoadExec に入り、さらに vmmdevR3HgcmLoadState に入る。これが UI:R である。残るのはパーサーであり、ゲストのハイパーコールではない。
VMMDev はデフォルトで有効。3D なし。Guest Additions なし。VRDP なし。PUEL ではない。
| ステップ | 場所 | 得られるもの |
|---|---|---|
| 復元 | ホスト UI / 保存済み VM に対する VBoxManage startvm | ホストユーザーが悪意ある .sav を開く。必要なクリックはこれだけである。 |
| SSM ユニット | VMMDev vmmdevR3HgcmLoadState (VMMDevHGCM.cpp:2043-2091) | SSMGetU32 により cParms に読み込まれ、VMMDEV_MAX_HGCM_PARMS (32) の上限がない。 |
| アロケーションのラップ | vmmdevR3HgcmCmdAlloc (VMMDevHGCM.cpp:376-381) | uint32_t cbCmd = sizeof(VBOXHGCMCMD) + cParms * (40+24)。cParms = 0x4000000 は約120にラップアラウンドする。そのサイズの RTMemAllocZ はヒープ予算に対して成功する。 |
| 最初のストア | ロードループ paGuestParms[i].enmType (VMMDevHGCM.cpp:2085-2091) | paGuestParms は pCmd + sizeof(VBOXHGCMCMD) であり、ラップアラウンド後はすでにアロケーションの終端である。最初の型 dword は4バイトの範囲外書き込みとなる。ストリームに必要なのは CALL ヘッダーと1つのパラメーター型だけである。6700万件のレコードは不要である。 |
| 種別 | 来歴 | 攻撃者が得るもの |
|---|---|---|
| 偵察 | なし | オーバーフローバイトは sav が選択する。これはリークではない。ヒープの内容はファイルに返されない。 |
| 完全性 | ラボ実証済み | cParms=0x4000000 は uint32_t cbCmd を 120 にラップする。1 回の i=0 の enmType ストアが 0xA5 カナリアを破壊する。canary0=56424f58 は VBOX-HGCM-SSM-CPARMS-WITNESS の VBOX プレフィックスである。対照の cParms=2 ではカナリアは無傷のままである。 |
| 完全性 | 推測 | さらなる sav 制御の parm レコード(型 dword に加えて 32/64 ビットまたはポインタ記述フィールド)は、VirtualBoxVM / VBoxHeadless 内の約 120 バイトの RTMemAllocZ から線形に書き込む。これは VM プロセス内の書き込みプリミティブであり、QEMU のマイグレーション memcorr と同じクラスである。本パックは命令ポインタの制御を実証するものではない。 |
| 可用性 | 推測 | 破壊が制御された書き込みに変換されない場合、VBoxVM はクラッシュする。ハーネスはカナリア破壊であり、VirtualBox プロセスのクラッシュではない。 |
vmmdevR3HgcmCallAlloc は依然として cParms > 32 を拒否する(VMMDevHGCM.cpp:921-926)。ゲストは正当な Save を通じてラップを仕込むことはできない。VMMDEV_MAX_HGCM_PARMS 32、VMMDEV_MAX_HGCM_DATA_SIZE 128MiB)。offValue / cbValue の memcpy は、HGCM クライアントが同じ sav で復元する場合にのみ、2 つ目のホストヒープ書き込みとなる。これは本ラボではない。完全なホストユーザー / ホストカーネルには、依然としてハードニングの残存物が必要である。この破壊を公開された IDispatch バイパスと組み合わせることは破棄する。
VirtualBox/virtualbox タグ v7.2.20 のピール f2792cf44 をピン留めした。CVE-2013-5892 がこのクラス(VBOXHGCMCMD への引数サイズラップ)であったため、稼働中の HGCM を最初に読んだ。稼働中のパスには依然として上限がある:
ASSERT_GUEST_STMT_RETURN( cParms <= (cbHGCMCall - sizeof(VMMDevHGCMCall)) / cbHGCMParmStruct
&& cParms <= VMMDEV_MAX_HGCM_PARMS,
LogRelMax(50, ("VMMDev: request packet with invalid number of HGCM parameters: ...")),
VERR_INVALID_PARAMETER);
Load は行いません。vmmdevR3HgcmLoadState は sav から cParms を受け取り、同じアロケータを呼び出します:
const uint32_t cbCmd = sizeof(VBOXHGCMCMD) + cParms * (sizeof(VBOXHGCMGUESTPARM) + sizeof(VBOXHGCMSVCPARM))
+ (enmCmdType == VBOXHGCMCMDTYPE_CONNECT ? sizeof(HGCMServiceLocation) : 0);
AssertCompile のこのピンに関するコメントでは、CMD が 120、guestparm が 40、svcparm が 24 とされています。cParms = 0x4000000 により、64 ビットの積は 0x100000000 + 120 になります。uint32_t への格納では 120 が保持されます。次に:
for (i = 0; i < cParms; ++i)
{
VBOXHGCMGUESTPARM * const pGuestParm = &pCmd->u.call.paGuestParms[i];
rc = pHlp->pfnSSMGetU32(pSSM, &u32);
pGuestParm->enmType = (HGCMFunctionParameterType)u32;
paGuestParms は pCmd + sizeof(VBOXHGCMCMD) に位置する。ラップ後、そこはアロケーションの終端となる。最初のストアはすでに OOB である。
すでに記録済みの誤った道筋:ライブ HGCM を残存物として扱うこと(依然として 32 で上限される);ハーネス内で 6700 万回のストアを走査すること(最初の dword が証拠である);ゲストが Save を通じてこれを仕込めると主張すること;VM プロセスのヒープ破壊をホストカーネルエスケープへと誇張すること;公開 IDispatch を連鎖させること。
見せかけ:リバースシェル、.sav パーサー、VirtualBox の起動。オラクルはラップと VBOX-HGCM-SSM-CPARMS-WITNESS のカナリア破壊である。
cd lab
./run.sh
またはパックのルートから:
python3 vbox-hgcm-ssm-cparms-Abraxas-Labs.py
ループバック 127.0.0.1:19210 上のソースハーネス。Compose プロジェクト vbox-hgcm-ssm-cparms。gadget.c はピンサイズ、uint32_t cbCmd の計算式、ライブ 32 の上限、および 1 つのロードパス enmType ストアをコピーする。VirtualBox を起動せず、.sav も解析しない。ループバックにバインドすること。
SUCCESS vbox-hgcm-ssm-cparms wrap=yes oob=yes live-cap=32 canary-smashed=yes VBOX-HGCM-SSM-CPARMS-WITNESS
vmmdevR3HgcmLoadState(および v17 より前の cLinAddrs パス)において、vmmdevR3HgcmCallAlloc がすでに行っているのと同じ方法で、SSM の cParms を VMMDEV_MAX_HGCM_PARMS に上限設定する。cbCmd を uint64_t / size_t でサイズ指定し、ラップを拒否する。保存された状態の整数は、稼働中のゲストの整数よりも信頼できるものではない。
f2792cf44f663989818507e36d3db5f978523c5e)VMMDevHGCM.cpp のライブ上限 · アロケーションのラップ · SSM ロードVMMDEV_MAX_HGCM_PARMSAbraxas Labs - abraxaslabs.tech - github.com/abraxas - @abraxas_null - [email protected]