In this blog post I want to discuss a code injection vulnerability in VMware Horizon‘s macOS Client Version 4.4.0 (5164329) that can be abused to gain local root privileges. The good news is, that it has already been fixed in the latest available version. I found it after learning about the “Open VMware View Client Services” SUID binary on my Mac.
I think it is used internally by Horizon’s remote USB services and is only exploitable after they have been started once by entering administrative credentials.
To investigate the binary further, I used the newly released Fireeye application Monitor.app. It basically is Process Monitor (procmon) for macOS.
Based on the activities as captured by Monitor.app it was clear that “Open VMware View Client Services” was basically a wrapper around “services.sh”. This makes sense as the SUID bit is ignored for script files.
After taking a closer look at this script, I identified the highlighted line in the following screenshot as a starting point for a possible code injection vulnerability. Although I had no idea about the inner workings of “./vmware-usbarbitrator” this binary was immediately my focus for further investigations. The reason for this is that I – as a non-admin user – am able to set the content of the environment variable VMWARE_VIEW_USBARBITRATOR_LOG_OPTIONS – that is used in an SUID executed script.
After taking a closer look at the possible command line options I was pretty sure I could abuse this setup to load a custom kernel extension by abusing the –kext flag.
However, there are two further problems:
- Kernel Extensions are only loaded if they are owned by root : wheel
- Additionally, KEXTs the have to be signed by Apple.
In the course of this LPE I will ignore issue #2. Hence, I disabled SIP.
So let’s focus on issue #1. To successfully load a kernel extension the binary has to be owned by root : wheel. However, for a normal user it is impossible to set this file system permissions on a any local file. Luckily, I had already invested plenty of time to learn about the In’s and Out’s of file systems at Tools On Air. So I knew, the only thing I had to do was to abuse NFS. This is possible because NFS allows the server to specify the file system permissions, even if mounted by a user. Any other local or remote file system I know of, ignores files owned by root in some way. So my next step was to simply export a remote folder (on my Kali Linux I always carry around with me) using NFS…
… and mount it using Finder’s “Connect to Server”.
After creating a simple KEXT …
and updating the Info.plist file to meet the requirements (simply add a dictionary “IOKitPersonalities”) we are ready!
After copying this KEXT to the NFS server and adapting its permissions to meet the “root:wheel” requirement, we are finally able to start the real exploitation.
To do so simply set the “VMWARE_VIEW_USBARBITRATOR_LOG_OPTIONS” environment variable to our previously create KEXT and run “Open VMware View Client Services”. This is enough to load it!
Hence, we gained code execution from a normal user’s account within the kernel context!
Suggested Solution
Filter or clear the environment variables VMWARE_VIEW_USBARBITRATOR_LOG_OPTIONS and VMWARE_VIEW_USBD_LOG_OPTIONS.
Disclosure Timeline
21-04-2017: The issues has been documented and reported
24-04-2017: VMware started investigating
06-06-2017: Fix ready
08-06-2017: Updated Horizon version 4.5 alongside security advisory VMSA-2017-0011 released