Oracle VM VirtualBox - Environment and ioctl Unprivileged Host User to Host Kernel Privilege Escalation







Become a Certified Penetration Tester

Enroll in Penetration Testing with Kali Linux and pass the exam to become an Offensive Security Certified Professional (OSCP). All new content for 2020.



This bug report describes two separate issues that, when combined,
allow any user on a Linux host system on which VirtualBox is installed
to gain code execution in the kernel. Since I'm not sure which one of
these issues crosses something you consider to be a privilege boundary,
I'm reporting them together.

To reproduce, download the attached file
virtualbox-host-r3-to-host-r0-crasher.tar, ensure that at least one VM
is running, then:

/tmp$ tar xf virtualbox-host-r3-to-host-r0-crasher.tar
/tmp$ cd virtualbox-host-r3-to-host-r0-crasher/
/tmp/virtualbox-host-r3-to-host-r0-crasher$ ./
./ line 7: 82634 Killed                  QT_QPA_PLATFORM_PLUGIN_PATH=fake_qt_platform_plugins /usr/lib/virtualbox/VirtualBox --startvm
/tmp/virtualbox-host-r3-to-host-r0-crasher$ dmesg
[279468.028025] BUG: unable to handle kernel paging request at 0000000013370028

The first step of the attack is to get access to the device
/dev/vboxdrv, which can normally only be opened by root:

~$ ls -l /dev/vboxdrv
crw------- 1 root root 10, 54 Jan 17 16:23 /dev/vboxdrv

In order to be able to open this device, the main VirtualBox binary is
setuid root:

$ ls -l /usr/lib/virtualbox/VirtualBox
-r-s--x--x 1 root root 35240 Jan 16 19:55 /usr/lib/virtualbox/VirtualBox

VirtualBox uses its root privileges to open /dev/vboxdrv, then quickly
drops its privileges. However, it retains the open file descriptor to
/dev/vboxdrv. Therefore, an attacker can gain access to the device
/dev/vboxdrv by injecting code into a VirtualBox userspace process.

After dropping privileges, VirtualBox loads various libraries,
including QT, that are not designed to run in a setuid context.
See :
"Qt is not an appropriate solution for setuid programs due to its
large attack surface." Using the environment variable
QT_QPA_PLATFORM_PLUGIN_PATH, an attacker can let QT load a library
from an arbitrary directory.

The second step is to use the device /dev/vboxdrv to corrupt the
kernel. The SUP_IOCTL_CALL_VMMR0 ioctl takes a pointer to a structure
in ring 0 as an argument (pVMR0) and ends up calling the function
VMMR0EntryEx(). With the attached PoC, this function crashes when
attempting to read pVM->pVMR0. However, an attacker who supplies a
pointer to attacker-controlled kernel memory could reach any point in
the function. For some operations, e.g.
VMMR0_DO_VMMR0_INIT, the attacker-controlled pointer pVM is then used
in vmmR0CallRing3SetJmpEx() to save and restore various kernel
registers, including RSP. By supplying a pointer to which the attacker
can concurrently write data, an attacker can therefore control the
kernel stack and thereby perform arbitrary operations in the kernel.
(As far as I can tell, a comment in VMMR0EntryEx points out this
issue: "/** @todo validate this EMT claim... GVM knows. */")

Proof of Concept: