# Cato VPN Client: Split-Tunnel and Privilege Escalation (CVE-2026-10739)

Cato VPN client's SYSTEM service used attacker-supplied SID in a file path, enabling path traversal and a privileged delete chained to a SYSTEM shell.

- Payout: Research
- Severity: high
- Program: Cato Client
- Write-up by: Lucas Laise
- Disclosed: 2026-09-30
- CVE: CVE-2026-10739
- Write-up quality: 9/10
- Original: http://blog.quarkslab.com/cato-vpn-client-split-tunnel-and-privilege-escalation-cve-2026-10739.html
- Library page: https://bugbountylibrary.com/r/blog%3Ablog-quarkslab-com-cato-vpn-client-split-tunnel-and-privilege-escalation-cve-2026-10739-html
- Tags: area:os domain:desktop impact:privesc kind:research platform:research sev:high tech:windows technique:chained technique:reverse-engineering technique:source-review vuln:auth-bypass vuln:path-traversal vuln:privilege-escalation

**Target:** Windows VPN client named pipe (\\.\pipe\cato-VPN) and split-tunnel upload flow
**Root cause:** The privileged service builds the split-tunnel output path as ccst_<client-supplied SID>.stp, trusting the SID from the protobuf message instead of the real client token, and does not reject ..\ components, allowing path traversal.
**Steps:**
1. Observe that uploading an invalid CCST file causes the SYSTEM service to delete the generated .stp file.
2. Note the pipe \\.\pipe\cato-VPN is gated by a certificate check on the connecting process image.
3. Manual-map a DLL payload into signed CatoClient.exe so the pipe connection passes the certificate check.
4. Send UiRegister with UserSidString set to `\\..\\..\\..\\..\\..\\..\\tmp\\foobar` to control the generated path.
5. Create symlink `C:\poc -> \RPC Control` and `\RPC Control\deleteme.stp -> \??\C:\Config.Msi`.
6. Send SplitTunnelUpload pointing to an invalid CCST file so cleanup deletes `C:\poc\deleteme.stp` as SYSTEM, resolving to C:\Config.Msi.
7. Use the Windows Installer rollback technique on the deleted C:\Config.Msi to execute code as SYSTEM.
**How found:** Noticed that invalid CCST uploads trigger a SYSTEM cleanup delete; checked directory ACLs (not writable), then traced the GUI-to-service IPC via named pipe tooling and Ghidra, found the cert check, bypassed it by manual-mapping into a signed process, and discovered the SID is client-controlled and used in the output path.
**Exploitation:** Low-priv user manual-maps a payload into signed CatoClient.exe to pass the pipe cert gate, registers with a traversal SID, then triggers invalid-CCST cleanup so the SYSTEM service deletes an attacker-redirected path (C:\Config.Msi via symlink), enabling MSI rollback to SYSTEM code execution.
**Escalation:** Chained SID path traversal + privileged file delete + symlink redirection + Windows Installer rollback (Config.Msi) to escalate from low-priv user to SYSTEM.
**Insight:** When a privileged service derives a filename from a client-supplied identity field (SID, UPN, username), test traversal in that field even if the directory ACLs look safe; a forced suffix like .stp can be neutralized with a symlink to redirect a privileged delete.

## Proof of concept (copied exactly from the original report)

**Attacker-controlled SID path traversal payload**

```
\\..\\..\\..\\..\\..\\..\\tmp\\foobar


The service then builds a path that still starts in the split-tunnel directory, but Windows normalizes the traversal and the final write reaches:

C:\tmp\foobar.stp
```

**Symlink redirection to Config.Msi for SYSTEM delete**

```
C:\poc -> \RPC Control
\RPC Control\deleteme.stp -> \??\C:\Config.Msi


Then the malicious SID points the generated .stp path to:

C:\poc\deleteme.stp
```

**Protobuf command IDs and body fields for pipe**

```
public enum BodyOneofCase
{
 UiRegister = 25,
 UploadStFile = 37,
 EnableLocalSt = 38,
}

public enum Commands
{
 UiRegister = 34,
 SplitTunnelUpload = 49,
 LocalSplitTunnelEnable = 50,
```

