CVE-2024-34331: Parallels Repack Privilege Escalation
Another day, another accidental exploit 🥳. This time abusing Parallels Desktop’s trust in macOS installers, gaining local privilege escalation!
- Affected Product: Parallels Desktop for macOS
- Affected Hosts:
x86_64
-based machines (ie. Intel Macs) - Affected versions: 16.0.0 through 19.3.0 (Originally reported against 19.2.1)
- Resolved version: 19.3.1
- Proof of Concept:
- Source Code: parallels_exploit.py
- Video Demo: Exploit Demo.mov
- CVE Associated: CVE-2024-34331
- Compensation: None
Vulnerability Discovery
While working with Parallels’ Mass Deployment package, I was testing against a 2018 Intel Mac mini and a macOS virtual machine. One odd thing I noticed during my tests was that a password prompt never appeared when it created my macOS VMs.
This was odd, as I was fairly certain Parallels was using Apple’s createinstallmedia
internally which requires root privileges. Upon further inspection, I confirmed this through a script called repack_osx_install_app.sh
located under Parallels Desktop.app/Contents/Resources
:
And look at that, no signature verification! Looks like an easy point to exploit 🤔.
But the question remains, how’s Parallels running createinstallmedia
as root without administrator credentials?
Magic of Set UID Bit
Originally I had believed Parallels installed some kind of XPC service to pass commands as root, however after searching I could not find any launch services associated with Parallels…
After finding Reno Robert’s amazing report, Bash Privileged-Mode Vulnerabilities in Parallels Desktop and CDPATH handing in macOS, I learned of a Unix trick called “Set UID bit” that a file can have.
What this S-Bit does is allow the executable to change its UID (user ID) to that of the file’s owner. And if the file’s owner is root, well now you get to run as root!
# Find all files with S-Bit set
/usr/bin/find . -perm -u=s
- Note that AppKit-based applications are explicitly prohibited from using this on stock macOS installs, instead another process will need to run them (ex.
Parallels Services
)- Reference: Cocoa Dev: setuid/setgid apps disallowed
Wait, is VMware Fusion also vulnerable to a malicious createinstallmedia?
Fun fact: Surprisingly not!
This is because of an odd script they developed called Create macOS Installer.tool
located under VMware Fusion.app/Contents/Library/
which attempts to create a valid installer manually and bypasses createinstallmedia
’s usage. However, this means it’s broken for modern macOS installers. But hey, no local privilege escalation 🎉
Intel-only Parallels Exploit
Something to keep in mind with this exploit is that it only affects x86_64-based hosts in macOS. This is due to the fact createinstallmedia
-based installers are incompatible with Apple’s Virtualization.framework stack on Apple Silicon, instead requiring IPSW restore images. Thus the vulnerable code path is never executed on Apple Silicon Macs.
What about versions of Parallels that didn’t check for Apple Silicon support?
This specific edge case relates to the timeline Apple Silicon launched. If an application was released before Apple Silicon, it will just assume the M-series Mac is just like any other Intel Mac.
When looking at Parallels Desktop 15.1.5 (47309), we see createinstallmedia
isn’t actually invoked inside of repack_osx_install_app.sh
. Instead, it uses hdiutil
to create a disk image similar to VMware Fusion. Only with Parallels Desktop 16, Parallels adds support for createinstallmedia
-based VMs, and at the same time checks whether the host can use it. Thus preventing the exploit from ever being triggered on Apple Silicon Macs.
The below error message is generated by ParallelsVirtualizationSDK.framework
when attempting to use a macOS installer on an Apple Silicon Mac:
Proof of Concept
Overall fairly straightforward:
- Create a macOS Installer app, with a malicious payload under
Contents/Resources/createinstallmedia
. -
Have Parallels Desktop open said application, and prepare it for installation.
i.
prl_client_app
takes the malicious macOS Installer appii.
prl_client_app
runsParallels Service
iii.
Parallels Service
runssetuid
raising privileges to rootiv.
Parallels Service
runsrepack_osx_install_app.sh
v.
repack_osx_install_app.sh
runscreateinstallmedia
as root
I have this process automated through parallels_exploit.py
, which creates a generic AppleScript payload to demonstrate root privileges and has Parallels load it.
And when we run said script, we get local privilege escalation!
Reporting Process
Filed through Parallels’ Responsible Disclosure system, we advised Parallels to implement code signature verification before executing createinstallmedia
.
- Notice in the above site that a valid License or Proof of Purchase is required, that’s unfortunate…
- Fun fact: My exploit works before even registering a product key!
Sender | Topic | Date |
---|---|---|
RIPEDA | Initial Report - 90+30 Disclosure Policy. | February 14th, 2024 |
Parallels | Initial response, asking for files in an alternative method. | February 25th, 2024 |
RIPEDA | Provided files. | February 25th, 2024 |
Parallels | Confirmed received files. | March 1st, 2024 |
Parallels | Released Parallels Desktop 19.3.0, still vulnerable. | March 7th, 2024 |
RIPEDA | Follow up. | April 17th, 2024 |
Parallels | Reminded internal team. | April 18th, 2024 |
Parallels | Released Parallels Desktop 19.3.1 without notifying us. | April 30th, 2024 |
RIPEDA | Confirmed vulnerability resolved | May 1st, 2024 |
MITRE | Assigned CVE-2024-34331 | May 7th, 2024 |
RIPEDA | Public Disclosure | May 30th, 2024 |
Verifying Parallels’ Work
By complete accident, we noticed Parallels Desktop 19.3.1 had been released one morning on April 30th, 2024. We knew 19.3.0 didn’t include our fix, thus curious if perhaps 19.3.1 does.
When examining repack_osx_install_app.sh
, we notice additional logic inside of do_repack_createinstallmedia()
. Specifically a code signature check against anchor apple
for createinstallmedia
binary:
# verify createinstallmedia is Apple-signed
/usr/bin/codesign -v -R="anchor apple" "$source_app/Contents/Resources/createinstallmedia"
if [ $? -ne 0 ]; then
echo "'$source_app' is not signed."
return $ERR_UNEXPECTED
fi
anchor apple
is for verification of Apple-signed binaries, likecreateinstallmedia
- Reference: Code Signing Requirement Language
And now when we run our parallels_exploit.py
again, it properly rejects our payload!
- The vague error messaging matches Apple’s own a bit too well…
Conclusion
A simple but fun exploit, and interesting to learn about the Set UID bit on files. Will be keeping an eye on S-Bit for future exploits.
Though shame Parallels doesn’t offer a bug bounty, especially being one of the most prominent virtualization solutions on macOS now since Apple Silicon. This only incentivizes researchers to sell exploits to make a living, rather than responsibly disclose them. I did discuss this with Parallels, however unknown if any changes will be made.
Ignoring all that, I also highly recommend others read Reno Robert’s report on their Parallels Exploit, lot of fun stuff in there: