VirtualBox E1000 integer underflow heap overflow (ACPI write primitive)¶
Emüle Intel E1000 NIC'inde bir VirtualBox guest-to-host escape:
e1kFallbackAddToFrame'deki (TCP-segmentation yolu) bir integer underflow, bir host heap overflow verir; bu EEPROM üzerinden bir write primitive'e ve ACPI SMBus state'i üzerinden bir read primitive'e dönüştürülür.
Mechanism¶
Note
VirtualBox, host VBoxHeadless/VirtualBox process'i içinde Intel 82540EM (E1000) NIC'ini
emüle eder. Guest, bir packet'i tanımlayan descriptor'lar postalayarak transmit'i sürer; TCP
segmentation (TSE) etkinken device, segment'leri bir host buffer'ında yeniden birleştirir.
Isolation invariant'ı, o buffer'a giden running offset'in buffer içinde kalmasıdır.
e1kFallbackAddToFrame() kalan alanı cb = u16MaxPktLen - pThis->u16TxPktLen olarak hesaplar.
Context+data descriptor'ları, halihazırda biriken u16TxPktLen (küçültülmüş) u16MaxPktLen'i
aşacak şekilde hazırlanırsa, çıkarma işlemi ~0xFFFFFFFF'e underflow eder, ardından gelen
cb > u20DTALEN kontrolünü atlatır ve e1kFallbackAddSegment'in PDMDevHlpPhysRead ile
buffer'ın tuttuğundan çok daha fazla byte okumasına izin verir — bir host heap out-of-bounds
write'ı; guest→host sınırını aşar ve NAT modunda guest ring-3'ten erişilebilir.
Walkthrough¶
Public referans: MorteNoir'ın virtualbox_e1000_0day'i (VirtualBox ≤ 5.2.20'yi etkiler;
CVE-2017-10235 / CVE-2019-2722 ile ilişkili). Kavramsal, zaten-public yol:
- Underflow'u tetikle beş-descriptor'lık bir dizilim ile
[context_1, data_2, data_3, context_4, data_5]: context_1max segment size'ı0x3010ayarlar;data_2+data_3,u16TxPktLen'e0x10byte biriktirir,data_3end-of-packet'i ayarlar (e1kLocateTxPacket'ten erken return).context_4max segment size'ı0xF'e küçültür;data_5(0x4188byte)0xF - 0x10'u underflow ettirir.- Aşırı büyük
cbşuraya ulaşır:kiPDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), PhysAddr, pThis->aTxPacketFallback + pThis->u16TxPktLen, u16Len);aTxPacketFallback[0x3FA0]'ı bitişikEEPROM93C46'ya taşırır. - Write primitive: EEPROM alanlarını (
m_fWriteEnabled,m_u16Addr,m_u16Word) bozmak,storeWord()'ün kontrollü bir 16-bit değeri kontrollü bir heap offset'inde yazmasını sağlar (m_au16Data[u32Addr] = u16Value). - Read primitive: write,
ACPIState::u8SMBusBlkIdx'i hedef alır ve guest I/O port0x4107üzerinden okunan 32-byteau8SMBusBlkDat'ı taşırarak ASLR'ı atlatmak içinVBoxDD.sopointer'ları sızdırır. - Loopback etkinken aynı underflow,
e1kHandleRxPacket'in stack buffer'ırxPacket[E1K_MAX_RX_PKT_SIZE]'a (0x4000) de ulaşır; bir host process spawn eden ve VM'i temizce sürdüren bir ROP chain için kaydedilmiş bir return address'i üzerine yazar.
Warning
Bug sınıfı için dokümante edilmiş, public ve patch'lenmiş bir sorun. Kesin ROP/host offset'leri atlanmıştır; bu kavramsal chain'dir.
Detection¶
- Host tarafı: E1000 TX aktivitesiyle korele
VirtualBox/VBoxHeadlesscrash'leri veya beklenmedik child process'ler; ASAN build'lerie1kFallbackAddToFrame/e1kHandleRxPacket'teki OOB'yi işaretler. - Davranışsal: max-segment-size'ı halihazırda biriken length'in altına küçülten TSE descriptor dizilimleri gönderen bir guest, gerçek bir NIC driver için anormaldir.
Mitigation¶
- Oracle'ın VirtualBox fix'ini uygula (CVE-2017-10235 / CVE-2019-2722); çıkarma işleminden önce
u16MaxPktLenileu16TxPktLen'i validate eder. - Mümkün olduğunda E1000 yerine paravirtualized virtio-net adapter'ını kullan, ya da güvenilmez guest'lere açılan NIC emülasyonunu kısıtla.
- Defense-in-depth: VM process'ini deprivileged/sandboxed çalıştır.
References¶
- MorteNoir, "VirtualBox E1000 Guest-to-Host Escape" (README): https://github.com/MorteNoir1/virtualbox_e1000_0day/blob/master/README.md
- STAR Labs — (CVE-2019-2722) Oracle VirtualBox e1000 Integer Underflow: https://starlabs.sg/advisories/19/19-2722/