During a recent research project we performed an in-depth security assessment of
Microsoft’s virtualization technologies, including Hyper-V and Azure. While we
already had experience in discovering security vulnerabilities in other virtual
environments (e.g.
here and
here), this was
our first research project on the Microsoft virtualization stack and we took
care to use a
structured evaluation strategy
to cover all potential attack vectors.
Part of our research concentrated on the Hyper-V hypervisor itself and we
discovered a critical vulnerability which can be exploited by an unprivileged
virtual machine to crash the hypervisor and potentially compromise other virtual
machines on the same physical host. This bug was recently patched, see
MS13-092 and
our
corresponding post.
In this post, we will focus on the DoS vulnerability, which is rated as
important and can affect the availability of the complete hypervisor and
potentially all cloud environments based on Hyper-V technology. We think that a
skilled and motivated attacker
can discover and exploit the vulnerability within two to four weeks without the
need for non-public knowledge (or a specific window of opportunity).
Due to the close relationship between the Hyper-V and Azure hypervisor and the
fundamental nature of the exploit, we assume that our Proof-of-Concept code will
affect the Azure Cloud environment as well. As MS13-092 is an official Microsoft
Security Bulletin, we furthermore assume that the vulnerability is patched in
Azure in the meantime.
The bug itself is caused by a mishandling of an error condition and was
discovered rather fast after the initial setup of our lab environment: Hyper-V
partitions can communicate with the hypervisor using so called
hypercalls.
They work similar to system calls that are used to communicate between ring 3
and 0 but operate between ring
0D
(“guest-ring-0”) and 0P (“hypervisor-ring-0”) instead. The actual implementation
differs between AMD and Intel systems but the overall interface is the same.
For Intel systems, the vmcall instruction is used to execute a hypercall.
Register rcx stores the hypercall number, rdx and r8 contain the guest
physical address (GPA) of supplied input and output parameters (we ignore the
so-called
fast calling convention
for now). On the hypervisor side, multiple checks are performed before the
hypercall handler is executed. This includes a check if the request originates
from Ring 0 (no such restriction is enforced by Intel. The vmcall instruction
can also be executed from user mode from an unprivileged partition (read:
typical virtual machine), if all supplied memory addresses are properly aligned.
In addition the user supplied input GPA is checked against an upper boundary as
illustrated in the next image:
If this check fails, the code continues through an error handling function and finally lands in the function at hv+0x2B42DC. This sub function uses the user controlled input address (now stored in rax) directly for a memory read as shown below:

Here,
by choosing the right value for our input address we can trigger an invalid
memory read and crash the hypervisor itself, resulting in the infamous BSOD.
We think this bug is an interesting example for the kind of issues that can
compromise the security and availability assumptions that many users might have
with regard to their hypervisors and virtualized environments. We will release
our PoC, further detail on the (even more interesting) privilege escalation part
and additional Hyper-V research at our
Troopers 14 talk.
Furthermore the bug will be discussed in much more detail in our
Exploting Hypervisors
workshop at Troopers.
Stay tuned,
Felix & Matthias
