Monday, December 23, 2024

State-backed attackers and commercial surveillance vendors repeatedly use the same exploits

Must read

The underlying bug is an optimization problem occurring during FTL JIT compilation. Both exploits also share the same exploitation framework, which provide attackers with a set of utilities to execute arbitrary code (e.g. custom MachO loader and parser, PAC and JIT cage bypasses).

There are several minimal differences between the two exploits, which include:

  • Failure mode. If something goes wrong during exploitation, the exploit from the watering hole will send back the information to the C2 and try to crash the browser with an out-of-memory error. If the Intellexa exploit fails, it does not send information back and will just redirect the user to a legitimate website.
  • Additional data collection from target device. The exploit from the watering hole has an additional function named dacsiloscope using the read/write primitives to collect even more information about the targeted device. This information is later used to decide whether or not the cookie stealer payload should be executed. For example, if the device doesn’t have PAC — which might be the case for an iPhone 8 running iOS 16.X — the cookie stealer payload will simply not execute.

Cookie stealer

The iOS exploit loaded the same cookie stealer framework that TAG observed in March 2021 when a Russian government-backed attacker exploited CVE-2021-1879 to acquire authentication cookies from prominent websites such as LinkedIn, Gmail and Facebook. In that campaign, attackers used LinkedIn Messaging to target government officials from western European countries by sending them malicious links.

In the watering hole campaigns, the flow on iOS versions older than 16.6 is the same as described in the Root Cause Analysis for CVE-2021-1879. For each targeted website:

  • Create a websocket w connected to an attacker-controlled IP address.
  • Set m_universalAccess to 1 inside the SecurityOrigin class by traversing a set of pointers.
  • Create a new URL object u pointing to the targeted domain.
  • Overwrite all Document URLS of the websocket w with the ones from the u URL.
  • Overwrite m_url field of the websocket w with the u URL.
  • Trigger a send on the websocket.
  • At the end of the websocket, the attacker receives requests as they would be delivered to the targeted websites u including the authentication cookies for the targeted websites.
  • Restore m_universalAccess back to its original state.

The cookie stealer module is targeting the following hard-coded set of websites:

[“webmail.mfa.gov.mn/owa/auth”, “accounts.google.com”, “login.microsoftonline.com”, “mail.google.com/mail/mu/0”, “www.linkedin.com”, “linkedin.com”, “www.office.com”, “login.live.com”, “outlook.live.com”, “login.yahoo.com”, “mail.yahoo.com”, “facebook.com”, “github.com”, “icloud.com”]

On more recent versions of iOS, the payload is calling WebCore::NetworkStorageSession::getAllCookies() to collect all cookies before exfiltrating them back to the C2.

Google Chrome campaign

At the end of July 2024, a new watering hole appeared on the mfa.gov[.]mn website where track-adv[.]com was re-used to deliver a Google Chrome exploit chain to Android users. From a high-level overview, the attack and end goal are essentially the same as the iOS one — using n-day vulnerabilities in order to steal credential cookies — with some differences on the technical side. In this case, the attack required an additional sandbox escape vulnerability to break out of Chrome site isolation.

  • Instead of a simple iframe directly added into the HTML, the attackers are now using a piece of obfuscated javascript to inject the malicious iframe pointing to https://track-adv[.]com/analytics.php?personalization_id=.
  • Before sending any stages, crypto keys are generated and exchanged using proper ECDH key exchange. Previous campaigns received a static decryption key from the C2.
  • In both campaigns the attack uses indexedDB to store status information on the client side. In the iOS exploit the database was named minus and in the Chrome exploit the database was named tracker.
  • A unique identifier using the same format (e.g., 2msa5mmjhqxpdsyb5vlcnd2t) was generated and passed as tt= parameter during all stages.

Latest article