Earlier in 2025, an apparent sender from 193.29.58.37
spoofed the Libyan Navy’s Office of Protocol to send a then-zero-day exploit in Zimbra’s Collaboration Suite, CVE-2025-27915, targeting Brazil’s military. This leveraged a malicious .ICS file, a popular calendar format.
The exploitation of Zimbra, Roundcube, and similar open-source collaboration tools, directly over email, is rare. Although actors do compromise the servers in broad campaigns, and attackers frequently leverage these tools as lures, actually exploiting a vulnerability in them with an email attachment is a thread worth pulling on. We previously blogged about an adjacent, but related attacker, and ESET has authored multiple authoritative blogs on the topic. Proofpoint has reported in depth about usages of XSS to steal individuals' mailboxes, and Palo Alto has shown some conceptually similar preview pane vulnerabilities in Outlook. XSS has often been seen as a “lesser” vuln compared to RCE, but these examples should hammer home that XSS can be just as effective at accomplishing a goal. There is a very small subset of attackers who are adept at finding these 0days. A Russian-linked group is especially prolific, responsible for the bulk of the above references, although recently UNC1151 also used similar TTPs.

Figure 1: spearphish email
TLDR: we discovered this by watching for ICS files > 10kb that contain javascript. This is a rare enough occurrence that you can put an eyeball on every one.

Figure 2: ICS containing obvious javascript
Carving and decoding this base64 gives familiar looking obfuscation to our previous blog. Our first step in the analysis process is to try tools such as Obfuscator.io Deobfuscator.

Figure 3: First phase of deobfuscation using deobfuscate.io
Considerable manual analysis (renaming variables, function names, and constants) would be required to fully understand the payload purpose.
However, the payload functionality can also be understood by making an html file which loads the javascript in the script
html header

Figure 4: loading the JS via html
One could then debug it by right-clicking and selecting inspect on the webpage using devtools, then going to the sources section where the JS is present. Lastly, set a breakpoint as shown below:

Figure 5: setting a breakpoint
The script is a comprehensive data stealer targeting Zimbra Webmail. It does the following:
-
Exfiltrates data to
https://ffrk.net/apache2_config_default_51_2_1
-
Employs evasion techniques like adding a 60 second delay before code execution, leverages 3 day execution windows, and also hides UI elements like
InvHeaderTable
to reduce visual clues -
Steals a wide range of data like credentials, emails, contacts, and shared folders
-
Monitors user activity. If the user is inactive, it logs them out and steals data
-
The code is implemented to be executed in asynchronous mode and into different Immediately Invoked Function Expressions (IIFE)
Below, we describe a few of the more interesting capabilities in the stealer
1) Limited Execution Frequency
Purpose: Only executes if 3+ days have passed since the last execution

Figure 6: function names changed for readability

Figure 7: checking to see if more than 3 days have passed
2) Data Exfiltration
Purpose: Sends stolen data to the attacker’s server using POST request and mode as “no-cors”

Figure 8: Sending an HTTP POST with the snarfed data
3) Hiding Elements
Purpose: Hides UI elements to reduce visibility of the attack

Figure 9: Hiding UI Elements
4) Requesting Zimbra Server for Retrieving Information
Purpose: Defines a helper function which sends SOAP requests to Zimbra Server for retrieving information

Figure 10: helper function
Detailed Breakdown of Each Async IIFE
A. First Async IIFE: Credential Theft & Activity Monitoring
1. Function Name: createHiddenFieldsForUsernameAndPasswordCapturing()
Purpose:
-
Creates hidden input fields for username and password
-
These fields are invisible to the user but can capture credentials when the user logs in

Figure 11: Creating Hidden Fields for Credentials Capturing
2. Function Name: stealUsernameAndPasswordFromLoginForm()
Purpose:
-
Steals usernames and passwords from login forms
-
Sends the stolen credentials to the attacker’s server

Figure 12: Stealing Username and Passwords on login forms
3. Function Name: startActivityMonitoring()
Purpose:
-
Monitors user activity (mouse movements, clicks, keyboard input)
-
If the user is inactive for a particular amount of time, it triggers data theft and logs the user out

Figure 13: Activity Monitoring
B. Second Async IIFE: Email Theft
1. Function Name: isMetadataLoaded()
& setMetadataLoaded()
Purpose:
-
Checks if metadata is already loaded to avoid re-execution
-
Sets a flag to prevent duplicate execution

Figure 14: Checking Meta data Loading
2. Function Name: searchForEmailsInFolderAndSendToAttackerServer()
Purpose:
-
Searches all email folders for emails
-
Sends the email content to the attacker’s server
-
Repeats every 4 hours to ensure continuous data theft

Figure 15: Sending Email Content from Folders
3. Function Name: searchEmailsInFolder(folder)
Purpose:
-
Uses Zimbra’s SOAP API to search for emails in a specific folder
-
Retrieves email IDs and sends the email content to the attacker

Figure 16: Searching for emails in folders
C. Third Async IIFE: Malicious Email Filter Rules
1. Function Name: addMaliciousFilters()
Purpose:
-
Adds malicious email filter rules to forward emails to
spam_to_junk@proton.me

Figure 17: Adding email filter rules
2. Function Name: addMaliciousEmailFilterRuleAndForwardToProtonMail(isOutgoing)
Purpose:
-
Creates a new email filter rule named "Correo". Interestingly, Correo is a Spanish word for mail, and in Brazil, where they speak Portuguese, it would traditionally be spelled Correio.
-
Forwards all emails to
spam_to_junk@proton.me

Figure 18: Forwarding emails to Proton Mail Account
D. Fourth Async IIFE: Stealing Scratch Codes, Trusted Devices, and App-Specific Passwords
1. Function Name: stealScratchCodeTrustedDevicesGetAppSpecificPasswords()
Purpose:
-
Steals scratch codes, trusted devices, and app-specific passwords
-
Sends the stolen data to the attacker’s server

Figure 19: Stealing Data
E. Fifth Async IIFE: Stealing Contacts, Distribution Lists, and Shared Folders
1. Function Name: stealContactsAndDistributionLists()
Purpose:
-
Steals contacts, distribution lists, and emailed contacts
-
Sends the stolen data to the attacker’s server

Figure 20: Stealing Data
2. Function Name: stealSharedFolders()
Purpose:
-
Steals shared folders
-
Sends the stolen data to the attacker’s server

Figure 21: Stealing Data
Type |
Value |
---|---|
Attacker c2 |
https://ffrk.net/apache2_config_default_51_2_1
|
Sender IP |
193.29.58.37
|
Email forwarding |
spam_to_junk@proton.me
|
Email attachment hash |
ea752b1651ad16bc6bf058c34d6ae795d0b4068c2f48fdd7858f3d4f7c516f37
|
Figure 22: Indicators mentioned in blog
Our github provides a download of the relevant files mentioned in the blog, including the deobfuscated JS.
Vendor |
Threat Actor name |
---|---|
Proofpoint |
UNK_HeatSink
|
Figure 23: Other validated vendor names for this actor
Acknowledgements
Thanks to K. Shahzad, as well as peer vendors, for their analysis and corrections Please get in touch at research@strikeready.com if you have corrections, would like us to use your group name, or would like to collaborate on research.