This post covers an exploit chain demonstrated by Nguyễn Hoàng Thạch (@hi_im_d4rkn3ss) of STAR Labs SG Pte. Ltd. during the Pwn2Own Vancouver event in 2023. During the contest, he used an uninitialized variable bug and a stack-based buffer overflow in VMware to escalate from a guest OS to execute code on the underlying hypervisor. His successful demonstration earned him $80,000 and 8 points towards Master of Pwn. All Pwn2Own entries are accompanied by a full whitepaper describing the vulnerabilities being used and how they were exploited. The following blog is an excerpt from that whitepaper detailing CVE-2023-20869 and CVE-2023-20870 with minimal modifications.
Prior to being patched by VMware, a pair of vulnerabilities existed within the implementation of the virtual Bluetooth USB device inside VMware Workstation. During the event, the VMware version used was 17.0.1 build-21139696. An attacker could leverage these two bugs together to execute arbitrary code in the context of the hypervisor. To exploit this vulnerability, the attacker must have the ability to execute high-privileged code on the guest OS. Bluetooth functionality is also required, but this is enabled by default. These bugs were patched in late April with VMSA-2023-0008.
CVE-2023-20870 – The Uninitialized Variable Info Leak
In VMware Workstation, in the USB Controller setting, there is the “Share Bluetooth devices with the virtual machine” option. This is enabled by default. It allows guest OSes to use Bluetooth devices. This functionality is handled by the Vbluetooth component, which is implemented in the vmware-vmx.exe binary. The VBluetooth device information can be read by
lsusb command (in Linux) as follows:
Each time a guest OS sends a USB Request Block (URB) request to the VBluetooth device, the function
VUsbBluetooth_OpNewUrb() is invoked to allocate memory to read or write data. The following code snippet is the
sub_140740EB0 function in vmware-vmx.exe:
This function returns a
VUsbURB object. Data is stored in this object in the
urb_data buffer. This buffer is allocated by the
RBuf_New() function and assigned to
urb_data at . Note that the
RBuf_New() function calls the
malloc function to allocate memory, so the memory is uninitialized. Then, the URB data is handled by
VUsbBluetooth_OpSubmitUrb() function. This code snippet is from the
sub_140740F50 function in vmware-vmx.exe:
total_urb_len is the length of data the guest OS wants to read from or write to the URB. This value is controllable by the attacker. At ,
total_urb_len is assigned to
urb->urb_actualsize without a check. Then, based on the endpoint type and URB packet, the corresponding function is invoked. Afterwards,
urb->urb_actualsize is set again in the handler function, but only if the packet is valid. We can see in the
VUsbBluetooth_OpSubmitUrb() function that if the
urb_data->bRequest is an invalid opcode (checked at ),
urb->urb_actualsize will not be set, and it will remain set to an attacker-controllable value.
UHCI_UrbResponse() function is invoked to send data back to the guest. The following snippet is in the
sub_1401F7C50 function in vmware-vmx.exe, corresponding to assembly code from address
A maximum of
urb->urb_actualsize bytes of data from the
urb->urb_data buffer will be returned to the guest. Since an attacker could control the value of
urb->urb_actualsize and the
urb->urb_data buffer is uninitialized, the guest OS could read uninitialized data from the heap.
CVE-2023-20869 – The Stack-based Overflow
The VBluetooth device also implements an Service Discovery Protocol (SDP) feature. When a guest OS wants to send an SDP packet to a specific Bluetooth peer, it must initialize a L2CAP connection to this peer. This is done by sending an
L2CAP_CMD_CONN_REQ packet to the
L2CAP_SIGNALLING_CID channel with the Protocol/Service Multiplexer (PSM) field set to 0x1. The result is a newly created SDP socket. This socket is used when processing subsequent SDP operations.
The SDP protocol data unit (PDU) format is well explained here. When the host OS processes an SDP PDU from the guest, it invokes
SDPData_ReadElement() to parse the PDU. Here’s a look at the
SDPData_ReadElement() function from the
sub_14083C1D0 function in vmware-vmx.exe:
The switch-case  is used to parse the data element size descriptor to determine the size of the raw data. Then this size is passed to
SDPData_ReadRawInt() to parse the unsigned int at .
Here’s another code snippet. This one is from the
sub_14083C570 function in vmware-vmx.exe. Since the PDU is submitted by the guest OS, an attacker can control the
size argument, which leads to a possible stack buffer overflow at /.
These bugs were combined at Pwn2Own Vancouver to pop calc on the target system. The exploit itself started in the guest OS while the calculator spawned on the host OS.
Thanks again to Nguyễn Hoàng Thạch for providing this write-up and for his participation in Pwn2Own Vancouver. He has participated in multiple Pwn2Own contests, and we certainly hope to see more submissions from him in the future. Until then, follow the team on Twitter, Mastodon, LinkedIn, or Instagram for the latest in exploit techniques and security patches.
Written by admin
ZDI-23-1494: Apple Safari TypedArray copyWithin Integer Underflow Remote Code Execution VulnerabilitySeptember 30, 2023This vulnerability allows remote attackers to execute arbitrary code on affected installations of Apple Safari. User interaction is required to exploit this vulnerability in that the target must visit a malicious page or open a malicious file.
ZDI-23-1493: G Data Total Security GDBackupSvc Service Link Following Local Privilege Escalation VulnerabilitySeptember 30, 2023This vulnerability allows local attackers to escalate privileges on affected installations of G Data Total Security. An attacker must first obtain the ability to execute low-privileged code on the target system in order to exploit this vulnerability.
September 30, 2023This vulnerability allows local attackers to disclose sensitive information on affected installations of the Linux Kernel. An attacker must first obtain the ability to execute high-privileged code on the target system in order to exploit this vulnerability.