Back to Blog
Expert Intelligence & Analysis

0day .ICS attack in the wild

Authors
StrikeReady Labs
PublishedSeptember 30, 2025
Est. Read Time6 min read

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.

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.

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.

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

1<!DOCTYPE html> 2<html> 3<head> 4<title>Debugging app</title> 5</head> 6<body> 7<h1>Hello World</h1> 8<script src="mal_decoded2.js"></script> 9</body> 10</html>

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:

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

2) Data Exfiltration

Purpose: Sends stolen data to the attacker’s server using POST request and mode as “no-cors”

3) Hiding Elements

Purpose: Hides UI elements to reduce visibility of the attack

4) Requesting Zimbra Server for Retrieving Information

Purpose: Defines a helper function which sends SOAP requests to Zimbra Server for retrieving information

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

2. Function Name: stealUsernameAndPasswordFromLoginForm()

Purpose:

  • Steals usernames and passwords from login forms
  • Sends the stolen credentials to the attacker’s server

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

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

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

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

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

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

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

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

2. Function Name: stealSharedFolders()

Purpose:

  • Steals shared folders
  • Sends the stolen data to the attacker’s server
TypeValue
Attacker c2https://ffrk.net/apache2_config_default_51_2_1
Sender IP193.29.58.37
Email forwardingspam_to_junk@proton.me
Email attachment hashea752b1651ad16bc6bf058c34d6ae795d0b4068c2f48fdd7858f3d4f7c516f37

Figure 22: Indicators mentioned in blog

Our github provides a download of the relevant files mentioned in the blog, including the deobfuscated JS.

VendorThreat Actor name
ProofpointUNK_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.

End of Intelligence Briefing

Share this Post0day .ICS attack in the wild
0%