Skip to main content
Blog
Blog

AppsFlyer Web SDK supply-chain compromise - polymorphic crypto stealer

A registrar-level DNS hijack of appsflyer.com served a polymorphic crypto-stealing payload through the AppsFlyer Web SDK and affected thousands of sites and some Node.js server environments. This post summarizes telemetry, forensic indicators, IOCs, detection guidance, and remediation steps.

Mar 18, 2026 9 min read
AppsFlyer Web SDK supply-chain compromise - polymorphic crypto stealer cover image
Table of Contents

TL;DR: AppsFlyer SDK v0.0.60 silent downgrade DNS hijack

  • Registrar hijack, real domain: AppsFlyer's servers were never touched. The attackers grabbed the registrar account, flipped the nameservers, and served a downgraded SDK from the real domain. Perimeter tools were watching the wrong perimeter.
  • Silent version downgrade: The compromised SDK silently rolled from v0.0.60 (hash 7dbae31c) back to v0.0.59 (hash db0c4f61), replaced window.fetch and scanned the DOM for wallet addresses across browser and Node.js variants. cside logged the alternating hashes days before the incident went public.
  • Compare hashes now: If you consume any vendor SDK by CDN URL, compare served versions and hashes against a known-good baseline today. If you cannot enforce SRI (dynamic SDKs will not allow it), add runtime API-override and DOM-mutation detection before the next silent downgrade lands.

Short on time? See cside's in-browser Magecart and skimmer blocking. It covers everything below in one deployment.

A malicious actor compromised the domain infrastructure serving the AppsFlyer Web SDK and injected a polymorphic crypto-stealing payload into thousands of websites. The attackers hijacked DNS at the registrar level, which bypassed standard security controls and let them serve malicious code from what looked like legitimate AppsFlyer endpoints. The injected script replaced the native window.fetch API, monitored the DOM for cryptocurrency addresses, and sent victim data to attacker-controlled command and control servers. Node.js server-side environments were targeted too, putting SSR frameworks and build pipelines at risk.

What cside's telemetry shows

Before the incident was widely known, cside's Script Insights telemetry recorded unusual behavior from the AppsFlyer Web SDK. Starting on March 1, cside observed two different script hashes being served from the official AppsFlyer endpoint across the monitored network. The rotation began before the incident was confirmed, which suggests the attackers were testing their deployment infrastructure or deliberately serving polymorphic builds to avoid detection.

cside's telemetry confirmed that major platforms loaded the compromised SDK. Specific domains are being withheld while affected organizations complete remediation. For the prescriptive controls that contain this class of incident, see our best practices for securing third-party scripts against supply-chain compromise.

The entry vector: a registrar-level DNS hijack

The attackers did not breach AppsFlyer's AWS infrastructure or internal repositories. They gained control through a registrar-level DNS hijack.

By compromising the domain registrar account for appsflyer.com, the attackers changed its authoritative nameservers. DNS records show that at the start of the attack, the nameservers for appsflyer.com changed from AWS Route 53 to ns1.gcorelabs.net (GCore CDN).

Once in control of DNS, the attackers routed all traffic for websdk.appsflyer.com through their own servers. They intercepted requests for the legitimate SDK and delivered a malicious, downgraded payload. Because the compromise occurred at the DNS layer, this method bypassed standard perimeter defenses and server-side protections.

The primary forensic indicator: a silent version downgrade

Since the attackers controlled DNS, they did not alter the core logic of the AppsFlyer SDK, only used it to deliver their payload.

The clearest sign of tampering was a silent version downgrade. The baseline SDK before the incident was version 0.0.60 (hash 7dbae31c...). During the attack, the version served from the official endpoint reverted to 0.0.59 (hash db0c4f61...). Legitimate updates do not roll back version numbers, so this is clear evidence of tampering.

cside compared the clean and downgraded SDKs and identified three modified lines. The attackers removed specific banner endpoints and changed the internal version string.

// Clean SDK (0.0.60)
VERSION:"0.0.60"
banner.appsflyer.com/
banner.appsflyer.com/sb/
dismissInjectPixel // present in clean build

// Compromised SDK (0.0.59)
VERSION:"0.0.59"
banner.appsflyer.com/ // .sb/ endpoint removed
// dismissInjectPixel function removed

The attackers avoided altering fvalid.appsflyer[.]com or wa.appsflyer[.]com/events, which would have broken Subresource Integrity checks. Instead, they used the DNS hijack to route all appsflyer.com traffic through their infrastructure, where the malicious payloads were served.

After the attack, AppsFlyer moved its infrastructure to appsflyersdk[.]com and released a clean 0.0.61 build on that domain. The appsflyersdk[.]com domain, registered in August 2019, is owned by AppsFlyer.

Deobfuscating the polymorphic payloads

Traffic routed through the compromised servers carried the crypto-stealing payload. Analysis of three malicious files revealed a polymorphic deployment approach with two obfuscation schemes targeting separate execution environments.

Build type 1: the browser payload (c7adfa8e)

The first payload, about 170KB in size, runs in the browser's global window scope. It uses custom base91 encoding with an 83-character alphabet to decode a 786-entry string table at runtime.

In a sandbox, this payload replaces window.fetch and registers a MutationObserver to scan the DOM for cryptocurrency addresses. It also adds an internal module called NetHooksmith to the window object (window.lIXMkR.NetHooksmith).

Build type 2: the Node.js wrappers (87e46457 & 9b0fac22)

The second variant, found in two builds of about 250KB each, uses a different obfuscation technique aimed at server environments. Instead of base91, these files enclose core logic in nested Function() constructors and decode strings through a rotating constant array combined with String.fromCodePoint.

These wrappers use getter objects to hook into Node.js contexts: for example get GKSDgsL(){return global} and get F1t0ak(){return exports}. Node.js applications, SSR frameworks, and build pipelines that imported the SDK through npm or bundlers were susceptible.

cside intercepted fromCodePoint calls during sandbox execution to obtain the decoded strings, which confirmed that the wrappers executed the same core fetch replacement logic but used separate wallet addresses. This points to dedicated infrastructure for server-side compromise.

The two wallet clusters and C2 infrastructure

Sandbox analysis identified two distinct attacker wallet clusters. The browser payload (Build type 1) contained one set of addresses, and the Node.js payloads (Build type 2) contained another. Both stored these in a global walletAddresses object.

Cluster 1 (browser payload c7adfa8e)

  • ETH: 0x1C069d0c73087D0Bae687a6f74a807350dCe1829
  • BTC: bc1qr7ngtnsh66demm4vzt4kmqxkqj8sqprnuklalt
  • SOL: 4LJi6mAczxZWbUvbMEk5scKhUZNPvfMDTjaVADkPFSsK
  • XRP: rntqwheGbZihkabxf6xqZkUKGfTVyRhT14
  • TRX: TV6WtAkS4aAMJb3Rt2bfs8LxggF8Kmqbd9

Cluster 2 (Node.js wrappers 87e46457 & 9b0fac22)

  • ETH: 0x782B93e52e62F25Bd002eeAA813B5A3fe49C9558
  • BTC: bc1q5nlx0exu0efldavw08wnjzpzluudaqh2qwlmjj
  • SOL: B5hMeV7B72xqcjypzxxoPmLpNz3bi6VvZApQrnh8YwDP
  • XRP: rEL7cB3jQNqtoym8oFJ36w1z3QLy9GjU
  • TRX: T062f95a517fc05055b59e12c6f4b2a402

Command and control (C2) endpoints

The payloads communicated with two C2 endpoints on the hijacked infrastructure:

  1. https://websdk[.]appsflyer[.]com/v1/api/plugin - fetched new wallet addresses on initialization.
  2. https://websdk[.]appsflyer[.]com/v1/api/process - uploaded exfiltrated wallet addresses and metadata using a ?rd= query parameter containing XOR-obfuscated data.

Behavioral signatures and detection

Because the attackers rotated obfuscation schemes and wallet addresses, static signatures like YARA rules were ineffective. The behavior of the payloads, however, is consistent and can be detected.

Security teams should look for these indicators:

  • Console output: All payloads print "Generating new wallets..." to the console during initialization.
  • fetch replacement: The payload overwrites the native fetch API to intercept outbound requests with cryptocurrency addresses.
  • Global object pollution: The payload creates a global walletAddresses object; the browser variant adds window.lIXMkR.NetHooksmith.
  • Console suppression: The browser payload uses 32 references to console methods to hide warnings and errors.
  • DOM mutation tracking: The browser payload registers a MutationObserver to scan new DOM elements for cryptocurrency address patterns.

Beyond the incident: the legitimate SDK's fingerprinting surface

Reviewing the clean SDK (hash 7dbae31c) revealed that the legitimate AppsFlyer PBA plugin collected extensive device fingerprinting data, including canvas font checks, ad-blocker detection, bot detection, and access to localStorage, sessionStorage, and indexedDB.

The SDK also loads additional code from fvalid.appsflyer[.]com/af/cp.sdk.1.2.7.js at runtime. Although common in marketing SDKs, this is an ongoing supply-chain risk. Organizations should assess the necessity of such tracking and apply strict Content Security Policies (CSP) and Subresource Integrity (SRI) to all third-party code.

How cside could have helped

A registrar-level domain hijack bypasses perimeter defenses and static analysis. cside's client-side security approach detects and blocks such attacks in real time through the following mechanisms:

  • Behavioral anomaly detection: cside monitors script actions rather than static signatures and alerts on attempts to overwrite window.fetch or access cryptocurrency inputs.
  • Network exfiltration blocking: If the payload runs, cside's network controls can block outgoing connections to C2 servers and stop wallet retrieval and data theft.
  • Hash rotation alerts: cside's telemetry detected alternating script hashes days before the attack became public, which allowed early investigation.
  • Version downgrade detection: cside logs exact versions and hashes of third-party scripts. A silent downgrade from v0.0.60 to v0.0.59 would trigger an immediate tampering alert.

By applying zero-trust measures on the client side, cside prevents compromised vendor scripts from exploiting user trust.

Indicators of compromise (IOCs)

  • Domain: appsflyer[.]com - Legitimate domain hijacked at registrar level
  • Nameserver: ns1.gcorelabs.net - Attacker-controlled nameserver during hijack
  • URL (C2): https://websdk[.]appsflyer[.]com/v1/api/plugin - Payload C2 endpoint (wallet rotation)
  • URL (C2): https://websdk[.]appsflyer[.]com/v1/api/process - Payload C2 endpoint (exfiltration)
  • URL parameter: ?rd= - Contains XOR-obfuscated exfiltration data
  • Wallet (ETH): 0x1C069d0c73087D0Bae687a6f74a807350dCe1829 - Cluster 1 (browser payload)
  • Wallet (BTC): bc1qr7ngtnsh66demm4vzt4kmqxkqj8sqprnuklalt - Cluster 1 (browser payload)
  • Wallet (SOL): 4LJi6mAczxZWbUvbMEk5scKhUZNPvfMDTjaVADkPFSsK - Cluster 1 (browser payload)
  • Wallet (ETH): 0x782B93e52e62F25Bd002eeAA813B5A3fe49C9558 - Cluster 2 (Node.js wrappers)
  • Console string: "Generating new wallets..." - Plaintext output by all payloads
  • Global object: walletAddresses - Injected by all payload variants
  • Global object: window.lIXMkR.NetHooksmith - Injected by browser payload
  • Version string: 0.0.59 - Downgraded SDK version indicating tampering

Recommendations

  1. Immediately compare the SDK version and hash served from any AppsFlyer endpoints you consume with known-good hashes; treat silent downgrades as high-priority tamper alerts.
  2. Block or sinkhole outgoing requests to the identified C2 endpoints and associated nameservers until remediation is complete.
  3. Harden CSP and apply SRI for third-party resources where feasible; consider self-hosting critical vendor scripts after verifying integrity.
  4. Scan server-side build pipelines and SSR deployments for the Node.js wrapper indicators described above and rotate any affected credentials.
  5. Deploy cside to watch for API overrides (like fetch) and DOM mutation scanning by third-party scripts.

This incident is not isolated. For a deeper look at how infrastructure laundering extends the threat beyond a single vendor compromise, see our analysis of sanctioned polyfill infrastructure. For a more recent case of the same delivery mechanism targeting DeFi users directly, see the Polymarket $3M client-side supply chain attack.

Forensic details, file hashes, and additional telemetry are available upon request to affected organizations and incident responders.

Note: This post summarizes findings from cside's Script Insights telemetry and sandbox analysis. Some specific domains and additional IOCs are withheld while impacted parties remediate.

Simon Wijckmans
Founder & CEO

Founder and CEO of cside. Previously a product manager on Cloudflare Page Shield (now Cloudflare Client-Side Security). Co-chair of the W3C Anti-Fraud Community Group and a Forbes 30 Under 30 honoree. Building accessible security against client-side attacks, web security is not an enterprise-only problem.

FAQ

Frequently Asked Questions

The attackers compromised the registrar account for appsflyer.com and changed authoritative nameservers to an attacker-controlled provider, which let them route legitimate subdomain traffic through their infrastructure. Because the change occurred at DNS, requests to the official SDK endpoint returned malicious payloads without modifying upstream AWS or repository assets, and this bypassed many perimeter and server-side controls.

The clearest forensic sign was a silent version downgrade from v0.0.60 to v0.0.59 served from the official endpoint; legitimate releases do not roll back version numbers. Comparing clean and compromised builds revealed removed banner endpoints and a removed function, consistent with a downgraded build used to host malicious code.

Look for behavioral indicators such as replacement of the native window.fetch, the creation of a global walletAddresses object, console output printing 'Generating new wallets...', and registration of a MutationObserver that scans the DOM for cryptocurrency address patterns. These runtime behaviors are consistent across polymorphic builds and are more reliable than static signatures.

The attackers also served Node-targeted wrappers that use nested Function() constructors and String.fromCodePoint decoding, and they expose getters returning global and exports objects (for example get GKSDgsL(){return global}). Detectable artifacts include unusual fromCodePoint decoding patterns, substituted fetch logic in server contexts, and the same walletAddresses objects with a different wallet cluster.

Compare served SDK versions and hashes against trusted baselines and treat any silent downgrades as tampering. Block the identified C2 endpoints and attacker-controlled nameservers, rotate any exposed credentials, scan build/CI pipelines for injected wrappers, and consider temporary self-hosting or removing the third-party SDK until integrity is verified.

Prioritize blocking the hijacked nameservers (for example ns1.gcorelabs.net observed during the incident), the C2 endpoints on the hijacked websdk subdomain (the /v1/api/plugin and /v1/api/process URLs), and specific wallet addresses while investigations continue. Also alert on console output 'Generating new wallets...' and creation of global objects like walletAddresses.

CSP limits the sources from which scripts may be loaded and can prevent execution of off-domain or unexpected resources; SRI enables browsers to verify script integrity using known-good hashes. Combined, these controls reduce the blast radius of DNS or CDN compromises by making it harder for attackers to execute unauthorized code in clients.

The attackers used polymorphism and rotated obfuscation schemes and wallet clusters to defeat static signatures, but their malicious behavior remained consistent: overwriting fetch, scanning the DOM for crypto addresses, creating wallet storage, and contacting C2 endpoints. Behavioral detection identifies these runtime actions and can block exfiltration regardless of string-level obfuscation.

Monitor and Secure Your Third-Party Scripts

Gain full visibility and control over every script delivered to your users to enhance site security and performance.

Start free, or try Business with a 14-day trial.

cside dashboard interface showing script monitoring and security analytics
Related Articles
Book a demo

Want to walk through this with an engineer?

Thirty minutes, on your own site. Not a slide deck.

We'll show you:

Which third-party scripts are running on your site right now
Where you stand on PCI DSS 6.4.3 and 11.6.1
How much of your traffic is bots and AI agents

Rather just send a question?

Finding open slots…

Real humans only. We'd know.

Having trouble booking? Open scheduler in a new tab

What are you trying to solve?

Tell us in a line and we'll come back with something useful, not a generic pitch.

We usually help with:

Seeing which third-party scripts run on your site
PCI DSS 6.4.3 and 11.6.1 evidence
Bots, AI agents and account takeover

Prefer to just book a time? Pick a slot instead