One Crafted Email, Zero Credentials: How Attackers Turned Zimbra SNMP Into Domain-Wide Mailbox Access

On 30 September 2026 Microsoft Threat Intelligence published its full tracking of CVE-2026-73570, an unauthenticated OS command-injection flaw in the Zimbra Collaboration Suite SNMP notification path. One specially crafted SMTP message, no login, and the attacker gets command execution as the zimbra service account — on the mail server that holds everyone's mailbox. The NVD record rates it CVSS 8.9 HIGH (CWE-78); CISA added it to KEV on 21 August 2026 with forensic triage required under BOD 26-04. The fix is Zimbra 10.1.20, released 20 July 2026; public disclosure followed on 13 August.

Read this the way Microsoft wrote it: not as a single bug, but as a worked example of what happens after the shell — webshells, a PAM-based privilege escalation to root, cluster-wide lateral movement over Zimbra's own SSH trust, theft of the keys that sign every session token, and a cloud-exfil attempt. If you run Zimbra with the optional zimbra-snmp package and SNMP notifications enabled, every section below applies to you.

The injection: SMTP in, snmptrap out

The vulnerable flow is narrow and damning. An attacker sends SMTP containing shell metacharacters; when a service-state change triggers health monitoring, swatchdog folds the attacker-controlled value into a snmptrap shell invocation without sufficient sanitization. Exploitation needs the optional zimbra-snmp package installed and SNMP notifications enabled — which is why so many estates are exposed without knowing it: an optional monitoring feature quietly widened the unauthenticated attack surface of an internet-facing mail server.

Microsoft's telemetry shows the flaw was found by more than one party. Between 28 July and 7 August — after the fix shipped but before public disclosure — two distinct scanning tools probed the same swatchdog-to-snmptrap path with lightweight out-of-band checks: HTTP callbacks carrying a ZB73570 User-Agent, DNS/ICMP callbacks to randomized subdomains on public collaborator infrastructure (oast.fun, oast.online, dnslog.pp.ua, requestrepo.com, bypass.eu.org), and curl/wget/ping/nslookup/id probes that dropped a small fingerprint script into the webroot. Someone was validating execution without delivering a payload — the standard precursor to a campaign, and a reminder that the patch-to-exploitation window here opened in July, not September.

From shell to webshells to root

Initial execution ran as the zimbra account, and the operators moved fast. They changed webroot permissions, reconstructed encoded payload fragments, wrote JSP webshells into publicly reachable Jetty and mailboxd application paths (plus copies on peer mailbox nodes), then deleted the fragments and — in some cases — restored the directory permissions to hide the change from casual checks. Parallel chains fetched remote content straight through wget/curl piped to a shell, launched background processes and interactive reverse shells, and kept recurring or memory-backed execution via cron, systemd, and memfd_create.

Privilege escalation abused Zimbra's own legitimate plumbing: a writable zmmailboxdmgr log directory, the sudo PAM stack with pam_exec, and the zmstat-fd helper. The sequence — symlink the mailbox log onto /etc/pam.d/sudo, invoke the privileged manager so the PAM file becomes zimbra-owned, plant a pam_exec hook, trigger sudo through the legitimate helper so the hook fires as root, write a NOPASSWD: ALL sudoers entry, then restore the originals — is worth studying because every step uses signed, expected binaries. Persistence followed the same mimicry logic: a zimlog.service systemd unit moved from /tmp into /etc/systemd/system, timestomped to match rsync and sshd, and enabled at boot.

They didn't steal mailboxes. They stole the keys to all of them.

The credential work is the part to sit with. Instead of individual passwords, the operators ran zmlocalconfig -s to expose LDAP, MySQL, Postfix, Amavis, and replication service credentials, then used them for authenticated LDAP queries pulling zimbraPreAuthKey, zimbraAuthTokenKey, and zimbraTwoFactorAuthSecret. A dedicated Go implant (zimbra-exfil/client-dump) automated the rest: reading localconfig.xml, dumping mailbox, metadata, mobile-device, and out-of-office tables plus the zimbra.* namespace, and staging certs, keys, and Postfix LDAP configs into timestamped /tmp/zimbra_dump_* archives. The auth-token key signs session tokens platform-wide — possession means minting sessions for arbitrary accounts without credentials — and the pre-auth key builds pre-authenticated login URLs for any user.

Lateral movement rode Zimbra's own cluster trust: the existing /opt/zimbra/.ssh/zimbra_identity key with host-key verification disabled, plus rsync transfers of fragments, helpers, and webshells between nodes with source cleanup. Command and control mixed HTTP/HTTPS callbacks, DNS-label channels, and an OpenSSL-encrypted reverse shell (/tmp/s named pipe, /bin/sh over s_client). A three-stage chain (agent2.sh → zimdown2 installer with SHA-256 verification → zimclient2 agent with shell, file ops, and SOCKS5 over WebSocket/TLS/TCP) gave resilient access with boot, cron, SSH-key, and local-account persistence. On one host the operators archived recent mailbox backups to /opt/zimbra/final.tar.gz and pushed it with AzCopy to an Azure Blob endpoint — Microsoft says the transfer's completion is unconfirmed, which is cold comfort once the staging happened. Victims span more than one region and industry; activity mixed automated delivery with hands-on-keyboard work.

What to do

  • Patch to 10.1.20 or later now. If patching must wait, uninstall the optional zimbra-snmp package, disable SNMP notifications, and restrict SNMP/SMTP to trusted hosts only.
  • Hunt for the injection signature, not just malware. A legitimate snmptrap invocation followed by shell metacharacters and a wget/curl call, wrapped in a trailing # that swallows the remaining arguments. Microsoft's tactical detector caught every confirmed event — but the most consequential outcome (full mail-store staging) involved a plain interactive shell with no malware family at all.
  • Rotate the platform keys, not just passwords. Rotate all domain zimbraPreAuthKey values, plus auth-token keys and 2FA secrets, and treat any session material minted before remediation as compromised.
  • Inspect every mailbox node, not just the alerting one. Look for unexpected JSP files, generated *_jsp.java/compiled servlet artifacts, permission flips on served directories, unexpected systemd units (ownership, enablement, timestamps), and SSH authorized-key or local-account additions. Removing one webshell does not end this incident.
  • Mind the retention gap. Defender XDR advanced hunting holds 30 days — the July pre-disclosure probing has aged out. Hunt the appendix infrastructure in Sentinel and archived logs, and pivot every indicator across the fleet. This site's recent KEV run — NetScaler zero-days exploited before the advisory, a SharePoint spoofing bug that was RCE all along, MikroTrick's pre-auth SSH takeover — keeps teaching the same lesson: edge and infrastructure RCE with KEV status means assume post-exploitation, preserve forensics before patching, and confine service accounts (namespace, seccomp, AppArmor) so the next command-injection buys less.

Sources: