2020-07-17 12:00 | Cees Elzinga

CVE-2020-3974: Privilege escalation in VMWare Fusion

VMware logo

VMware Fusion is a popular hypervisor for macOS. It allows users to run nearly any operating system on a Mac. We identified a local privilege escalation. This issue was assigned CVE-2020-3974 / VMSA-2020-0017 and was fixed in version 11.5.5 released on 2020-07-09..

XPC

VMWare Fusion has several components that need to run with high privileges. These all run as separate LaunchDaemons that run with root privileges. The rest of the program runs with the privileges of the normal user. The LaunchDaemons are configured here:

$ ls -al /Library/LaunchDaemons/com.vmware.*
-rw-r--r--  root  558 /Library/LaunchDaemons/com.vmware.DiskHelper.plist
-rw-r--r--  root  536 /Library/LaunchDaemons/com.vmware.IDHelper.plist
-rw-r--r--  root  586 /Library/LaunchDaemons/com.vmware.KextControlHelper.plist
-rw-r--r--  root  562 /Library/LaunchDaemons/com.vmware.MountHelper.plist
-rw-r--r--  root  562 /Library/LaunchDaemons/com.vmware.VMMonHelper.plist

To facility communication between these daemons Apple recommends to use a technology called XPC. XPC is an inter-process communication framework build on top of Mach. The main reasons for using XPC are privilege separation and stability. One of the features provided by XPC is the ability to filter incoming connections. We will see how VMware uses this later to (try) to block certain connections.

Looking at the content of a LaunchDaemon script shows it registers an XPC service called com.vmware.IDHelper. The other daemon register services with similar names:


$ cat /Library/LaunchDaemons/com.vmware.IDHelper.plist
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.vmware.IDHelper</string>
    <key>MachServices</key>
    <dict>
        <key>com.vmware.IDHelper</key>
        <true/>
    </dict>
    <key>Program</key>
    <string>/Library/PrivilegedHelperTools/com.vmware.IDHelper</string>
    ...

Vulnerability

Any user can connect to the XPC services registered above. That is not an issue in itself, but since the services run as root it makes them an interesting target for attackers. Great care should be taken in handling the data. The most critical step is to decide if an incoming connection is trusted or not. At this point the service should deny any unauthorized connections.

Unfortunately, the Apple documentation does not show the correct way of doing this. Even more so, to actually do so securely developers need to go through some trouble and use a private symbol. you can think of this as an undocumented feature. Not surprisingly this resulted in many bugs in many products before. And as we will see, VMware Fusion has a similar issue.

When a client connects to a VMware LaunchDaemon it always starts by verifying the incoming connection:

  • Receive a request
  • Store the process identifier (pid) of the sender
  • Resolve the executable (path) for this pid
  • Extract the code signature of the executable
  • Verify the code signature

If any of these steps fails the request is rejected.

The vulnerability lies in the way the executable for a pid is resolved. The implementation is vulnerable to a race condition. An attacker can send a malicious request, quickly swap his process with one that passes all the remaining verifications, and pass the checks.

Decompiled code from com.vmware.IDHelper

VMware IDHelper pid lookup

At the moment the function proc_pidpath is called the pid might belong the a different process. This is shown in the following diagram:

VMware authentication flow

The important steps are marked with numbers:

  1. Client sends a (malicious) request to com.vmware.IDHelper
  2. Client quickly swaps it's process and starts a VMWare signed binary with the same PID
  3. Server checks binary that belongs the the requests PID
  4. Server sends response back to the client. This fails, but it doesn't matter for exploit described below. Code execution is already achieved when handling the request.

The vulnerability is the time between check (1) and (3). An attacker can race this window and try to swap out the binary at (2).

Exploit

The vulnerability allows any user to call functions exported by the LaunchDaemons. This is already interesting, but further exploitation depends on the functions that the programs export. This exploit uses a function exported by com.vmware.IDHelper called collectSupportInformation. This particular function generates problem reports, and does so by calling an external program:

VMware idhelper report

The external program used to create the reports is supplied by an attacker. It might look like an attacker can just supply any program he wants, but if you look carefully in the snippet above you can see VMware performs additional checks on the program. Even though the client should already have been verified as this point, the daemon still doesn't trust the input and first verifies the code signature of the program. This is a good example of defense-in-depth, and more work it required to get code execution.

The exploit uses a second bug: a command injection in the script /Applications/VMware Fusion.app/Contents/Library/VMware Fusion Problem Reporter.tool. This script is signed by VMware and therefore passes all the checks. At line 365 this tools evaluates one of the arguments:

if [ ! -z $DEFUSER ]; then
   printf -v HOME %s $(eval echo ~$DEFUSER)
fi

By setting a username that includes back-ticks this results in code execution. The script will continue executing after that and start generating error reports. To prevent this the exploit sets some additional arguments to trigger a special code path at line 408 to prevent further execution of the script:

# Cancel running support tool

if [ "$CANCEL_PID" ]; then
   printf "Cancelling process %08x\n" "$CANCEL_PID"
   /bin/kill -9 "$CANCEL_PID"
   exit # Use the status of the last command.
fi

Full exploit.

For developers

If you are developing an XPC service and want to do so securely there are some good (unofficial) resources available. Objective Development has a great blog post on how they ran into a similar issue and the process they went through to fix it.

If you are looking for example code you can take a look at SimpleXPCApp by Wojciech Reguła or LuLu by Objective-See.


Contact us

+45 3113 7316

[email protected]

Vester Farimagsgade 41, 1606 Copenhagen V

Consulting | Training | Blog | About

© 2020 Danish Cyber Defence A/S · Vester Farimagsgade 41 · 1606 Copenhagen V · CVR 38871064