Skip to content

Hyper V Security

Hyper-V Security

Hyper-V is a native hypervisor written by Microsoft and intended to run Windows XP+ and various Linux guests under a Windows Server or Windows 10 host. A free standalone edition also exists: Microsoft Hyper-V Server 2016 (as of May 31st, the 2019 edition has been delayed indefinitely). Like other bare-metal hypervisors, it allows guest VMs to communicate directly with the host through a dedicated channel (in this case, “VMBus”). In the interest of having a unified codebase between real and virtualized OSes, Windows 10 installations (Professional and higher) contain VMBus drivers already loaded and ready to go. There are some quirks to VMBus that make it interesting, including the ability to nest VMs and PowerShell remoting capabilities. In most other regards, Hyper-V is pretty much the same as other hypervisors, e.g. ESX{,i} and ProxMox.

Source

VMBus

In order to pass information between the guest and host, Microsoft wrote a ring buffer that uses RNDIS for communication. Among other things, this permits guest/host communication via network-style sockets (which is the focus of this post) via the mostly undocumented address family 36 (note this doesn’t appear documented anywhere other than in PowerShell source code). Listening and sending on these sockets do not require special privileges, and since the default network stack is not used, they do not obey Windows firewall rules. Additionally, this allows the guest to communicate with the host, even if the guest has no NIC attached at all, and to potentially exfiltrate data that normally would be confined to the VM.

Shielded VMs, Guarded Fabric, and Host Guardian Services

In order to try and address the threat scenario where the host is malicious or the host’s admin has been compromised, Microsoft invented an optional flow to isolate VMs from their hosts. VMs are “shielded” when they run on “guarded fabric” by means of a “host guardian service”. Shielded VMs are VMs that are encrypted at-rest and are decrypted via calling a service called the Host Guardian Service (HGS). This service can (and should) exist separately from the VM host (the “fabric”), and details of communications between the HGS and the shielded VM can’t be observed by the host (due to asymmetric encryption). Since the guest is encrypted and the host doesn’t have the decryption key, an evil admin can’t meaningfully tamper with the data or machine state. Incidentally, shielded VMs also automatically do not run various helper services such as PowerShell Direct, which adds even better hardening.

Security Concerns

Built-in Hyper-V Services

Hyper-V guests have several pre-installed services that sit waiting for an external trigger and then start up. We will only focus on one, PowerShell Direct. Note that there are some interesting threats in that if you can convince a real bare-metal install that it’s a VM, it will helpfully start up a service that allows you to PowerShell into it via VMBus. The services appear to have registered in a common DLL “icsvc.dll”.

Hyper-V PowerShell Direct Service

PowerShell allows remote users to connect and open interactive shells, called PowerShell Remoting. There are restrictions on this service, such as requiring administrative access on the target and permitting a custom ACL; the service can even be disabled organization wide. PowerShell Direct is pretty much the same idea (and has similar commands) but without the overhead of firewalls, functioning NICs, or event admin privileges on the target guest machine. If an attacker compromises a Hyper-V Administrative account and has valid credentials (e.g. any domain user), they are free to pass that along to all VMs and pop PowerShells on all them. This works regardless of the firewall configuration or valid IP address. The user only needs to be a member of the Hyper-V Administrator group on the host machine.

The service runs as LocalSystem and listens on a Hyper-V Socket for a connection. New connections receive plaintext domain+user+password information and verify it using normal SSP (SSPLogonUser probably). If the creds are valid, a new token is created as that user and "powershell.exe" is executed with this token (CreateProcessAsUserW). There's several issues here, running as LocalSystem is obviously not ideal, but also the connection doesn't support any sort of safer credential exchange such as challenge/response, Kerberos, anything!

PowerShell Direct: Malicious Guest Attack

The service runs as LocalSystem and listens on a Hyper-V Socket for a connection. New connections receive plaintext domain+user+password information and verify it using a normal SSP (SSPLogonUser probably). If the credentials are valid, a new token is created for that user and “powershell.exe” is executed with this token (CreateProcessAsUserW). There are several issues here: running as LocalSystem is obviously not ideal, but also the connection doesn’t support any sort of safer credential exchange such as challenge/response or Kerberos. Windows appears to perform basic signature checking, since the relevant DLL is cryptographically signed by a Microsoft catalog entry but may still be bypassable (e.g. Windows only checks that the service is some valid signed file, not that it is the expected DLL in particular). In this case, a malicious local administrator on the guest can replace the DLL with a service that will log all incoming PowerShell Direct credentials for later use.

Additional Research

  • Create a guest/host program that leverages the Hyper-V socket bindings
  • Create a malicious DLL to replace the normal guest service and grabs the PowerShell Direct creds

Additional Resources