Hyper-V vmswitch VmsMpCommonPvtHandleMulticastOids kernel-pool overflow¶
Bir guest, length'i vmswitch.sys tarafından yanlış ele alınan RNDIS OID_802_3_MULTICAST_LIST request'leri gönderir ve bir host non-paged pool buffer'ının birkaç byte ötesine kopyalar — bir guest-to-host kernel-pool overflow.
Mechanism¶
Note
vmswitch.sys (Hyper-V virtual switch, host kernel), guest RNDIS OID request'lerini VMBus
üzerinden işler. OID_802_3_MULTICAST_LIST (0x01010209), bir NIC'in multicast address
list'ini — 6-byte'lık MAC entry'lerinden oluşan bir buffer'ı — ayarlamasına izin verir.
VmsMpCommonPvtHandleMulticastOids handler'ı, entry count'unu request data length'ini 6'ya
bölerek ve remainder'ı atarak hesaplar.
Açık, iki request arasındaki bir state mismatch'tir. Host, ilk request'ten türetilen count
için boyutlandırılmış bir non-paged pool buffer (mcMV tag'i, ExAllocatePoolWithTag ile)
allocate eder ama sonraki copy, atılan remainder'ı içeren bir length kullanır:
- Request 1: data length
6*N-> buffer6*Nbyte için boyutlandırılır. - Request 2: data length
6*N + Y(Y = 1..5) ->6*Nbyte'lık buffer'a6*N + Ybyte kopyalanır.
Sonuç, bir host non-paged pool allocation'ının controlled bir 1–5 byte overflow'udur.
(Vulnerable state — buffer pointer ve entry count — public analizde object offset'leri 0xEE0
ve 0xEE8'de tutulur.)
Isolation boundary'sini aşar çünkü overflow olan allocation ve copy'yi gerçekleştiren kod host kernel'de (R0) yaşar; length ve içerik ise bir guest içinden tamamen attacker-controlled'dur. Attacker-influenced kernel object'lerine bitişik bir pool overflow, guest-to-host privilege escalation için klasik primitive'dir (public PoC'a göre "code execution in the context of the Host R0") ya da en azından host pool corruption / DoS'tur.
Warning
Küçük (1–5 byte) olsa da, off-by-a-few bir non-paged pool overflow, bitişik pool chunk header'ı ya da object groom edilebildiğinde exploit edilebilir. Microsoft bunu erken Windows Server 2016 Technical Preview build'lerinde sessizce (CVE atanmadan) düzeltti.
Walkthrough¶
Public PoC (Exploit-DB 39713), multicast OID için iki crafted RNDIS Set request'i verir; ikincisi 6'nın temiz bir katından biraz daha uzundur.
Conceptual two-request overflow (from the public PoC)
OID = 0x01010209 // OID_802_3_MULTICAST_LIST
Request 1 (sizes the allocation):
set->oid = 0x01010209
extlen = 16 * 6 // 96 bytes -> count = 16, buffer = 96B
Request 2 (overflows):
set->oid = 0x01010209
extlen = (16 * 6) + 5 // 101 bytes copied into the 96B buffer
Host vmswitch.sys:
VmsMpCommonPvtHandleMulticastOids
count = len / 6 // remainder discarded on alloc sizing
buf = ExAllocatePoolWithTag(NonPagedPool/*200h*/, 6*count, 'mcMV')
memcpy(buf, guest_data, len) // len includes remainder -> +1..5 OOB write
Vulnerable bir host'ta beklenen etki: mcMV non-paged pool allocation'ının ötesine 1–5 byte'lık
bir write, host kernel'de bitişik pool belleğini corrupt eder.
Detection¶
- Bir guest'in network aktivitesiyle ilişkilendirilmiş,
mcMVpool tag'i ile non-paged pool corruption'a ya da faulting stack'tevmswitch.sys'e işaretlenmiş host bugcheck'leri. - Host kernel pool integrity check'lerini etkinleştirmek (
vmswitch.sysüzerinde pool tracking ile Special Pool / Driver Verifier), overflow'u daha sonra değil, out-of-bounds write anında yüzeye çıkarır. - Tek bir guest'ten gelen, non-6-aligned length'lere sahip anormal tekrarlanan
OID_802_3_MULTICAST_LISTgüncellemeleri.
Mitigation¶
- Güncel bir Hyper-V servicing baseline çalıştırın; multicast-OID length handling'i erken Windows Server 2016 build'lerinde düzeltildi. Host'ları patch'li tutun.
- Guest-originated RNDIS OID verisini host kernel'a untrusted length-bearing input olarak ele alın; multi-tenant host'larda untrusted tenant'ları izole edin.
References¶
- Hyper-V — 'vmswitch.sys' VmsMpCommonPvtHandleMulticastOids Guest to Host Kernel-Pool Overflow — Exploit-DB 39713
- Critical 9.9 Vulnerability in Hyper-V Allowed Attackers to Exploit Azure — Akamai (separate, related vmswitch OID handler bug: CVE-2021-28476, an RNDIS OID arbitrary host read/pointer dereference — NOT the multicast OID overflow described here; included for general vmswitch-OID context)