
VirtualBox 7.2.20 - عالية - محلية - تجاوز سعة الكومة - HGCM SSM cParms wrap
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · vbox-hgcm-ssm-cparms
الفئة: تجاوز سعة الكومة (Heap overflow) الوصول: محلي (المضيف)
Oracle VM VirtualBox OSS 7.2.20 (f2792cf44) - Oracle
لا يزال HGCM المباشر يرفض cParms > 32. أما تحميل الحالة المحفوظة فلا يرفضه. يقرأ vmmdevR3HgcmLoadState قيمة cParms من ملف .sav دون حدّ VMMDEV_MAX_HGCM_PARMS، ثم يحدّد حجم الأمر باستخدام uint32_t cbCmd. عند cParms = 0x4000000 يلتفّ حاصل الضرب ليصبح sizeof(VBOXHGCMCMD) (~120). وأول عملية تخزين لـ enmType هي بالفعل كتابة بمقدار 4 بايت خارج حدود الكتلة.
مستخدم مضيف يستعيد حالة محفوظة خبيثة يُحدث تجاوزًا في كومة عملية الجهاز الافتراضي. ولا يستطيع الضيف زرع ذلك عبر Save.
| المعرّف | لا يوجد CVE بعد |
| الفئة | تجاوز سعة الكومة (كتابة خارج الحدود في عملية الجهاز الافتراضي؛ وليس هروبًا إلى نواة المضيف) |
| الوصول | محلي (المضيف) (UI:R استعادة الحالة المحفوظة / اللقطة) |
| CWE | CWE-190، CWE-787 |
| CVSS | مرتفع: 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) |
| المصادقة | مستخدم المضيف يستعيد جهازًا افتراضيًا محفوظًا أو لقطة أو ملف .sav |
| الترخيص | GNU Affero GPL v3.0 |
| المختبر | 127.0.0.1 فقط. أداة اختبار من المصدر. دون إقلاع VirtualBox، ودون تحليل .sav. |
تسليم المشغّل مجلد جهاز افتراضي تحمل حالته المحفوظة استدعاء VMMDev HGCM CALL معلّقًا. فينقر على Start لجهاز افتراضي محفوظ، أو يستعيد لقطة، أو يتبنّى ملف .sav. تمرّ استعادة وحدة التحكم عبر SSMR3 إلى vmmdevR3LoadExec ثم إلى vmmdevR3HgcmLoadState. هذا هو UI:R. والمتبقّي هو المحلّل، وليس استدعاءً فائقًا من الضيف.
VMMDev مفعّل افتراضيًا. لا 3D. لا Guest Additions. لا VRDP. وليس PUEL.
| الخطوة | المكان | ما تمنحه |
|---|---|---|
| الاستعادة | واجهة المضيف / 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 مع نوع معامل واحد. ولا يحتاج إلى 67 مليون سجل. |
| النوع | المصدر | ما يحصل عليه المهاجم |
|---|---|---|
| استطلاع | لا شيء | بايتات الفائض يختارها sav. هذا ليس تسريبًا. لا تُعاد محتويات الكومة إلى الملف. |
| السلامة | مُثبت مختبريًا | cParms=0x4000000 يلفّ uint32_t cbCmd إلى 120. مخزن enmType واحد بـ i=0 يحطّم كاناري بقيمة 0xA5. canary0=56424f58 هو بادئة VBOX الخاصة بـ VBOX-HGCM-SSM-CPARMS-WITNESS. التحكم cParms=2 يترك الكاناري سليمًا. |
| السلامة | مُستنتج | سجلات parm إضافية يتحكم بها sav (نوع dword مع حقول 32/64-بت أو حقول وصف مؤشر) تكتب خطيًا خارج RTMemAllocZ البالغ ~120 بايت في VirtualBoxVM / VBoxHeadless. هذا بدائي كتابة في عملية الآلة الافتراضية، من نفس فئة memcorr في ترحيل QEMU. لا تُظهر هذه الحزمة التحكم في مؤشر التعليمات. |
| التوافر | مُستنتج | انهيار 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. ليس هذا المختبر.لا يزال host-user / host-kernel الكامل بحاجة إلى مخلّف تقوية. الجمع بين هذا التحطيم وتجاوز IDispatch العام مستبعد.
ثبّتُّ VirtualBox/virtualbox عند الوسم v7.2.20 peel f2792cf44. كان HGCM الحي أول ما قرأته لأن CVE-2013-5892 كان من هذه الفئة: لفّ حجم الوسائط إلى VBOXHGCMCMD. لا يزال المسار الحي يحمل الحد الأقصى:
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 قيمة cParms من sav وتستدعي نفس المخصص:
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). بعد الالتفاف يكون ذلك نهاية التخصيص. أول عملية تخزين تكون بالفعل خارج الحدود.
المسارات الخاطئة المسجّلة مسبقًا: التعامل مع HGCM الحيّ على أنه المتبقي (فهو لا يزال محدودًا عند 32)؛ اجتياز 67 مليون عملية تخزين في الـ harness (أول dword هو الدليل)؛ الادعاء بأن ضيفًا يمكنه زرع هذا عبر Save؛ تضخيم تحطيم كومة عملية VM إلى هروب إلى نواة المضيف؛ تسلسل IDispatch العام.
المسرح: reverse shell، ومحلّل .sav، وإقلاع VirtualBox. الـ oracle هو الالتفاف بالإضافة إلى تحطيم canary الخاص بـ VBOX-HGCM-SSM-CPARMS-WITNESS.
cd lab
./run.sh
أو من جذر الحزمة:
python3 vbox-hgcm-ssm-cparms-Abraxas-Labs.py
مُحرِّض المصدر على loopback 127.0.0.1:19210. مشروع Compose vbox-hgcm-ssm-cparms. ينسخ gadget.c أحجام pin، وصيغة uint32_t cbCmd، والحد الأقصى الحي 32، ومخزن enmType واحد في مسار التحميل. لا يُقلع VirtualBox ولا يُحلِّل ملف .sav. اربطه بـ loopback.
SUCCESS vbox-hgcm-ssm-cparms wrap=yes oob=yes live-cap=32 canary-smashed=yes VBOX-HGCM-SSM-CPARMS-WITNESS
حدّد سقف cParms في SSM عند VMMDEV_MAX_HGCM_PARMS في vmmdevR3HgcmLoadState (ومسار cLinAddrs لما قبل الإصدار 17) بالطريقة نفسها التي يفعلها vmmdevR3HgcmCallAlloc بالفعل. اجعل حجم cbCmd من نوع uint64_t / size_t وارفض أي التفاف. العدد الصحيح القادم من حالة محفوظة ليس أكثر موثوقية من عدد صحيح قادم من ضيف حيّ.