CVE Tools
Back to blog

Zimbra's half-click XSS: how a CSS trick let Russian spies read government mail (CVE-2025-66376)

A stored XSS in Zimbra's Classic webmail became a zero-day mailbox-collection weapon. Here's the chain, the detections, and why patching alone won't evict the attacker.

Zimbra's half-click XSS: how a CSS trick let Russian spies read government mail (CVE-2025-66376). A stored XSS in Zimbra's Classic webmail became a zero-day mailbox-collection weapon. Here's the chain
Zimbra's half-click XSS: how a CSS trick let Russian spies read government mail (CVE-2025-66376). A stored XSS in Zimbra's Classic webmail became a zero-day mailbox-collection weapon. Here's the chain

Most cross-site-scripting bugs get a shrug and a medium score. This one got a mailbox. Zimbra's legacy webmail client had a hole in the code that scrubs incoming HTML email, and a Russian-nexus intelligence operation quietly drove a truck through it - reading government inboxes, stealing two-factor codes, and leaving behind a back door that survives a password reset. The scariest part isn't the exploit. It's how little the victim had to do: open an email.

What the flaw actually is

Zimbra runs every inbound HTML email through a server-side sanitizer - built on the OWASP AntiSamy engine - whose whole job is to strip anything that could execute code before the message reaches your browser. The bug is that the sanitizer failed to neutralize CSS @import directives embedded in a message. Attacker-controlled styling survived the scrub, was stored with the email, and executed JavaScript in the victim's authenticated webmail session when the mail was rendered in the Classic (legacy) UI. It's a textbook stored XSS (CWE-79) - the twist is where it lives: inside the trusted mail client, running as you.

The exact byte-level trick that got @import past the filter is not public, and no vendor root-cause write-up spells it out. What we do know is that Zimbra shipped the fix as an upgraded AntiSamy engine - after which admins reported the Classic client suddenly rejecting non-standard CSS in mail, exactly the behaviour you'd expect if the @import path was the thing that got tightened. Zimbra's HTML mail sanitizer has a long history of failing on some novel construct; this is the newest entry.

Why a 'medium' XSS became an espionage weapon

Attribution here is unusually firm for a webmail bug. Proofpoint tracks the operator as TA488 - overlapping with the cluster others call Void Blizzard / Laundry Bear - and a multinational government advisory led by the NSA, FBI and CISA (co-signed by the Netherlands, UK, Australia, Canada and others) corroborated the Russian-aligned attribution, while cautioning that these actor names may not map one-to-one. A separate report from Seqrite tied a January 2026 Ukraine-focused wave to APT28 at moderate confidence, so read the exact actor label with a little slack - the who is Russian intelligence collection; the precise crew name is contested.

What the JavaScript did is the real story. According to Proofpoint and reporting on the campaign, the implant (tracked as ZimReaper) ran inside the victim's webmail session and: lifted the CSRF/session token and the browser's saved password; pulled 2FA scratch codes and the server version via Zimbra's own APIs; walked the Global Address List; and exfiltrated up to roughly 90 days of mail as compressed archives, signalling over DNS. For persistence it minted an app-specific password named ZimbraWeb - which grants IMAP/POP/SMTP access without 2FA and, critically, survives a password reset - and silently switched IMAP on. Compromised servers were then used to send the next round of malicious mail. (Those operational specifics come from vendor reporting relaying the joint advisory, so treat the tool names and the 90-day figure as sourced-but-single-lineage.)

The exploitation chain

The power of this bug is the distance it covers with one click that barely counts as a click. Here's the path from a crafted email to a back door that outlives your incident response - and the two places you can break it: sanitize the CSS on render (the patch), or catch the stolen session doing suspicious things in your mail logs.

CVE-2025-66376 - Zimbra half-click XSS to mailbox collection

  1. 1. Crafted HTML email with CSS @import payload — Attacker sends an HTML email whose CSS @import smuggles JavaScript past Zimbra's AntiSamy sanitizer. No credentials needed to deliver.
  2. 2. Victim opens/previews mail in Classic UI — The payload is stored with the message and fires on view/preview in the Classic Web Client - a 'half-click'. Modern UI is not affected.
  3. 3. JavaScript runs in the authenticated session — Script executes with the victim's session authority in the Classic UI (ATT&CK T1059.007). No malware on the endpoint, no link to click.
  4. Patched to 10.0.18 / 10.1.13? — The fixed AntiSamy engine sanitizes the @import payload on render. This is the only durable break in the chain.
  5. Chain blocked - payload sanitized — On a fixed build the styling is neutralized before it can execute. Nothing runs.
  6. 4. Steal session/CSRF token, password, 2FA codes — ZimReaper harvests the CSRF token, saved password and 2FA scratch codes via Zimbra's own APIs (T1539 / T1111).
  7. 5. Enumerate GAL + exfil ~90 days of mail — Walk the Global Address List and exfiltrate ~90 days of mail as archives over HTTP(S), signalling via DNS (T1114 / T1048).
  8. 6. Persist: ZimbraWeb app-password + enable IMAP — Create an app-specific password 'ZimbraWeb' (IMAP/POP/SMTP without 2FA, survives password resets) and flip IMAP on (T1098). Patching does not remove this.
  9. 7. Re-spread from the compromised mailbox — The hijacked mailserver sends further exploit emails, widening the campaign.
  10. Detection chokepoint: mail-log Sigma + gateway YARA — Because the payload can't be reliably signatured, the cheapest catches are gateway @import/CSS inspection at step 1 and behavioural mailbox.log detection at steps 4-6.

Am I affected?

Two conditions have to both be true: you're running an affected build, and your users can reach the Classic Web Client. Only Classic UI renders the vulnerable CSS path - the Modern UI uses a different engine and isn't named in scope. Check your version as the zimbra user with zmcontrol -v, and remember the login-page banner leaks the build to anyone, which is how the attackers fingerprinted targets in the first place.

BranchVulnerableFixed buildNote
ZCS 10.0.xbefore 10.0.1810.0.1810.0 reached end-of-life 2025-12-31 - migrate to 10.1, don't park here
ZCS 10.1.xbefore 10.1.1310.1.13Current stable is later (~10.1.16); go as recent as you can
ZCS 9.xUnconfirmed-Official scope is 10.0/10.1 only; a '9.0.0 P46' claim looks conflated with a sibling CVE. Treat as unknown and upgrade regardless
Classic UI disabledNot exploitable-Modern UI isn't in scope; forcing Modern UI removes exposure to this path

The timeline: discovered in use, not in disclosure

This is the recurring shape of espionage-grade webmail bugs - the fix ships as a quiet patch for exploitation nobody had named yet, and public understanding lags the attacker by the better part of a year.

CVE-2025-66376 - from zero-day to joint advisory

  1. Exploited as an unknown zero-day
    TA488 / Void Blizzard begins abusing the flaw roughly five months before any fix exists.
  2. Zimbra ships the fix (10.0.18 / 10.1.13)
    Described as patching a stored XSS in the Classic UI abusing CSS @import directives. Reported patch date; the CVE record was published later.
  3. CVE-2025-66376 published to NVD
    The public record catches up to the November fix.
  4. Added to CISA KEV
    Federal civilian due date 2026-04-01; marked not used in ransomware. A separate Seqrite report ties a Jan 2026 Ukraine wave to APT28 (moderate confidence).
  5. Multinational joint advisory + Proofpoint write-up
    NSA/FBI/CISA-led advisory and Proofpoint's TA488 report publish the detailed attribution and TTPs, triggering the second press wave.

Detection & hunting

Here's the uncomfortable truth: there is no network scanner check that proves you were hit, and there never can be one for a bug that only fires inside a logged-in webmail session. A Nuclei-style probe can't reach the vulnerable code path - which is why the CVE shows zero Nuclei templates yet still has authenticated OpenVAS/Nessus version checks. So detection splits in two: authenticated version scans for exposure at fleet scale, and behavioural log hunting for compromise. The payload can't be reliably signatured, so you hunt the actions the stolen session performs.

Behavioural detections for CVE-2025-66376 exploitation2 rules
sigma ×1yara ×1

Authored heuristics, not vendor signatures. The stored-XSS payload in an email body can't be reliably matched, so the Sigma rule targets the high-signal actions a hijacked Zimbra session performs (from the reported ZimReaper IoCs), and the YARA rule flags the suspicious mail structure. Tune both to your environment and expect false positives from legitimate newsletters and admin activity.

sigmaZimbra webmail post-exploitation activity (mailbox.log)
App-specific-password creation ('ZimbraWeb'), 2FA scratch-code theft, silent IMAP enable, and filter/forwarding-rule creation performed right after a message is opened. Zimbra mailbox.log (/opt/zimbra/log/mailbox.log) with the SOAP request name extracted into a searchable field.
title: Suspicious Zimbra Webmail Post-Exploitation Activity (CVE-2025-66376)
status: experimental
description: Behavioural detection for actions a hijacked Zimbra Classic UI session performs after stored-XSS abuse (CVE-2025-66376) - app-specific-password creation, 2FA scratch-code theft, silent IMAP enable, filter/forwarding-rule creation.
author: cve.tools research (authored heuristic)
date: 2026-07-26
references:
  - https://thehackernews.com/2026/07/russian-espionage-group-exploited.html
  - https://www.riskinsight-wavestone.com/en/2025/12/zimbra-mailbox-compromise-from-analysis-to-remediation/
logsource:
  product: zimbra
  service: mailbox
detection:
  appspecific_password:
    message|contains: 'CreateAppSpecificPasswordRequest'
  scratch_codes:
    message|contains: 'GetScratchCodesRequest'
  filter_or_forward:
    message|contains:
      - 'CreateFilterRulesRequest'
      - 'ModifyFilterRulesRequest'
      - 'ModifyOutgoingFilterRulesRequest'
  imap_enable:
    message|contains|all:
      - 'ModifyPrefsRequest'
      - 'zimbraPrefImapEnabled'
      - 'TRUE'
  forward_pref:
    message|contains: 'zimbraPrefMailForwardingAddress'
  known_campaign_credname:
    message|contains: 'ZimbraWeb'
  condition: 1 of them
fields: [message, src_ip, account, user_agent]
falsepositives:
  - Legitimate app-specific passwords, filters, forwarding, or admin IMAP changes via zmprov
  - Backup/migration tooling that enumerates or exports mail
level: high
yaraHTML email abusing CSS @import (heuristic)
HTML mail that combines a CSS @import with a CSS script-injection primitive - the abuse pattern, not a specific payload. Raw .eml / stored HTML part at the mail gateway. High false-positive rate: legitimate newsletters use @import, so this requires @import AND an injection primitive.
rule Zimbra_CSS_Import_XSS_Suspect {
  meta:
    description = "Heuristic: HTML email using CSS @import with CSS script-injection primitives (CVE-2025-66376 abuse pattern)"
    reference = "CVE-2025-66376"
    author = "cve.tools authored-heuristic"
  strings:
    $style  = "
  • Hunt the mail logs, not the network. In /opt/zimbra/log/mailbox.log, audit.log and access_log, look for the post-exploitation chain firing seconds after a message read: an app-specific password named ZimbraWeb, zimbraPrefImapEnabled flipped to TRUE, bursts of GetScratchCodesRequest, Global Address List enumeration, or a large archive export.
  • Forwarding rules leave no log. Zimbra doesn't log forwarding-rule creation, so check account state directly: zmprov ga <account> zimbraPrefMailForwardingAddress zimbraMailSieveScript zimbraPrefImapEnabled.
  • Scan for exposure with authenticated checks. Use OpenVAS/Nessus version audits (or the login banner) to find builds below 10.0.18 / 10.1.13 across the fleet - don't wait for a Nuclei template, there isn't one.

What to do now

  1. Patch. Upgrade 10.0.x to 10.0.18 and 10.1.x to 10.1.13 (or later). There is no vendor workaround - the patch adds CSS sanitization on render. Because 10.0 is end-of-life, move those fleets onto 10.1, not just 10.0.18.
  2. Can't patch this hour? Force Modern UI and lock users out of Classic UI (zmprov mc <cos> zimbraPrefClientType modern and restrict the override), and quarantine or strip inbound <style>/@import at the mail gateway. These are stopgaps, not a fix.
  3. Assume breach if you were exposed. Patching does not evict this actor - the ZimbraWeb app-password survives a password reset. For any potentially-affected mailbox: invalidate all sessions AND reset the password, delete rogue app-specific passwords, regenerate 2FA scratch codes, revert unexplained IMAP-enable, and audit forwarding/Sieve rules.

FAQ

Is CVE-2025-66376 being exploited in the wild?
Yes. It's on CISA's KEV list (added 2026-03-18) and was used as a zero-day for months in 2025 by a Russian-aligned espionage actor before Zimbra patched it. There's no public exploit code, but KEV reflects confirmed real-world use - which is why its low EPSS score is not a reason to wait.
We're patched. Are we safe?
Patching closes the hole, but it does not undo a prior compromise. The campaign created an app-specific password ('ZimbraWeb') that survives password resets and silently enabled IMAP. If any mailbox could have opened a crafted email on a vulnerable build, treat it as compromised: invalidate sessions, reset credentials, delete rogue app passwords, regenerate 2FA codes, and audit forwarding rules.
Does this affect the Modern UI or SharePoint... I mean Zimbra Online?
The flaw is specific to the Classic (legacy) Web Client of on-premises Zimbra Collaboration Suite. The Modern UI uses a different rendering engine and isn't named in scope, so forcing users to Modern UI removes exposure to this particular CSS path while you patch.
Why is a 'medium' XSS such a big deal here?
Because the base score (7.2 from the CNA, 6.1 from NVD) rates data impact as Low, but the real-world payload drained ~90 days of mail, the Global Address List, saved passwords and 2FA codes, and left reset-proof persistence. For a webmail stored-XSS abused by an APT, the CVSS number is a floor, not a ceiling.

Sources