Skip to content

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 -> buffer 6*N byte için boyutlandırılır.
  • Request 2: data length 6*N + Y (Y = 1..5) -> 6*N byte'lık buffer'a 6*N + Y byte 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ş, mcMV pool tag'i ile non-paged pool corruption'a ya da faulting stack'te vmswitch.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_LIST gü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