Full Report
Within the VGAState struct of VirtualBox there is a bitmap used for tracking dirty pages of a VRAM buffer. This bitmap is large enough to use the maximum vram allowed by vbox at 256MB. When clearing the dirty bits, the start_addr is incorrectly multiplied by 4! If the address is larger than 64MB, then leads to an out of bounds access. What primitive does this give us? A heap based bit clear. Doesn't seem like a lot and seems inconsistent on the location. To trigger the bug, they set a bunch of setting within the ioport communication. How is this exploitable? Within VGAState, there is a section called CritSect. This is a critical section that can only be used by one thread at a time for in and out instructions for each devices MMIO region. The cLockers variable is effectively a locking variable to ensure that other threads don't access it at the same time. By abusing a bit clear, it could be possible to create an artificial race condition here. Using this race condition, there is a problem though: there is a secondary check on the ownership that will crash changing the owner . The flag RTCRITSECT_FLAGS_NOP determines whether locking operations are checked at all, which controls the check above. The idea is to use the original exploitation path to change the flag BEFORE the crash happens. Then, after that, we can continue using the race condition for other things. With the protections removed on the race condition detection, corruption is much easier to cause. The primitive used for corrupting the flag with the function vbe_ioport_write_data can be used once again to corrupt the size of the buffer cScratchRegion. With the size corrupted, it creates an easy out of bounds read and write. After the VGAState variable is PDMPCIDEV. Since this is part of the initial allocation, it's always in the same spot! It contains several function pointers, leading to easy code execution. Even with CFG turned on it doesn't matter because we control the pointer and two of the parameters being passed in. It's crazy how such a little bug turned into such a large impact. Awesome post on exploit development!
Analysis Summary
# Vulnerability: VirtualBox VGA Dirty Page Bitmap Out-of-Bounds Write Leading to LPE
This vulnerability description is derived from a write-up detailing an exploit that won Pwn2Own.
## CVE Details
- CVE ID: CVE-2024-21115
- CVSS Score: Not explicitly provided, but described as leading to Local Privilege Escalation (LPE) and code execution, suggesting a **High** severity score (9.0+).
- CWE: CWE-190 (Integer: Result Too Large or Too Small), leading to CWE-787 (Out-of-bounds Write).
## Affected Systems
- Products: Oracle VirtualBox
- Versions: Versions patched in the April 2024 CPU (specific vulnerable range not listed, but pre-April 2024 release).
- Configurations: Triggerable on default graphics controller (VMSVGA) with constraints as low as 32MB VRAM, though the successful exploit required 65MB to 128MB VRAM and 4 CPU cores.
## Vulnerability Description
The flaw exists within the `VGAState` structure, specifically in the logic used to clear dirty page bits in a VRAM tracking bitmap inside the `vgaR3DrawBlank` function. When clearing these bits, the `start_addr` is incorrectly multiplied by 4. If `start_addr` corresponds to a location greater than 64MB (relative to the VRAM buffer), this results in an **Out-of-Bounds (OOB) Write/Clear** in heap memory adjacent to the dirty page bitmap.
The exploit chains this heap bit-clear primitive to construct a race condition against the device critical section synchronization primitive (`CritSect` using `cLockers`). By corrupting the `hEvent` value within the `VGAState` critical section (changing it from its default value, e.g., `0x23`, to the value used by another device like `VMMDev`, e.g., `0x21`), the race condition can be exploited. This race condition is used to bypass a secondary self-check mechanism by changing the `RTCRITSECT_FLAGS_NOP` flag *before* the crash-inducing secondary check executes.
Once protections are bypassed, the initial OOB write primitive is reused via `vbe_ioport_write_data` to corrupt the size of the `cScratchRegion` buffer. This corruption facilitates arbitrary OOB read/write capabilities. Finally, this arbitrary access is used to overwrite function pointers within the adjacent, consistently located `PDMPCIDEV` structure (part of the initial allocation), leading to code execution upon dereference, even bypassing CFG because the attacker controls the function pointer and two parameters.
## Exploitation
- Status: **PoC available** (Write-up describes the complete exploitation chain used to win Pwn2Own).
- Complexity: **High** (Requires precise timing, multi-core setup, and knowledge of internal synchronization objects and memory layout/offsets).
- Attack Vector: **Local** or potentially **Adjacent** (via complex protocol interaction, but fundamentally relies on interacting with the virtual machine components from the guest). Given it leads to LPE, the initial entry point is assumed to be a guest process.
## Impact
- Confidentiality: **High** (Full guest system compromise allows reading sensitive data).
- Integrity: **High** (Full control over the guest process context, leading to arbitrary code execution).
- Availability: **High** (Can lead to denial of service in less complex attacks or full system takeover).
## Remediation
### Patches
- Patched by Oracle in the **April 2024 CPU**. Users must update to the corresponding patched version of VirtualBox.
### Workarounds
- No specific workarounds were detailed, but suggested mitigation would likely involve restricting access to configuration mechanisms that allow setting VRAM size or controlling ioport communication used to trigger the flaw, though this is highly restrictive for a functional VM.
## Detection
- Initial detection indicators revolve around abnormal behavior related to VRAM size settings via ioport communication or unusual heap operations near the VGA state structure.
- Advanced detection would require monitoring for the specific race condition timing or subsequent attempts to overwrite function pointers within known structures like `PDMPCIDEV`.
## References
- Vendor Advisory: hXXps://www.oracle.com/security/advisories/cpuapr2024.html
- Vulnerability Analysis: hXXps://www.zerodayinitiative.com/blog/2024/5/9/cve-2024-21115-an-oracle-virtualbox-lpe-used-to-win-pwn2own