Een kwaadwillende actor voerde een supply-chain-aanval uit door de domeininfrastructuur te compromitteren die de AppsFlyer Web SDK diende, en injecteerde een polymorfe crypto-stelende payload in duizenden websites. De aanval omzeilde beveiligingsmaatregelen door DNS op registrar-niveau te kapen, waardoor de aanvallers kwaadaardige code konden serveren vanaf wat leek op legitieme AppsFlyer-eindpunten. Het geïnjecteerde script verving de native window.fetch API, monitorde de DOM op cryptocurrency-adressen en stuurde slachtofferdata naar door de aanvaller beheerde command-and-control-servers. De aanval richtte zich ook op Node.js-serveromgevingen, waardoor SSR-frameworks en build-pipelines aan risico werden blootgesteld.
Wat de telemetrie van cside laat zien
Voordat het incident algemeen bekend was, registreerde de Script Insights-telemetrie van cside ongewoon gedrag van de AppsFlyer Web SDK. Vanaf 1 maart namen systemen waar dat twee verschillende scripthashes werden geserveerd vanaf het officiële AppsFlyer-eindpunt binnen het gemonitorde netwerk. Deze rotatie begon voordat het incident werd bevestigd, wat suggereert dat de aanvallers hun deploymentinfrastructuur testten of bewust polymorfe builds serveerden om detectie te vermijden.
Telemetrie bevestigt dat grote platforms de gecompromitteerde SDK hebben geladen. Specifieke domeinen worden achtergehouden terwijl getroffen organisaties het herstel voltooien. Voor de voorschrijvende maatregelen die dit soort incidenten indammen, zie onze best practices voor het beveiligen van externe scripts tegen supply-chain-compromittering.
De aanvalsvector: een DNS-kaping op registrar-niveau
De aanvallers hebben de AWS-infrastructuur of interne repositories van AppsFlyer niet doorbroken. Ze verkregen toegang via een DNS-kaping op registrar-niveau.
Door het domeinregistrar-account voor appsflyer.com te compromitteren, wijzigden de aanvallers de autoritatieve nameservers. DNS-records tonen dat aan het begin van de aanval de nameservers voor appsflyer.com veranderden van AWS Route 53 naar ns1.gcorelabs.net (GCore CDN).
Eenmaal in controle van DNS routeerden de aanvallers al het verkeer voor websdk.appsflyer.com via hun eigen servers. Ze onderschepten verzoeken voor de legitieme SDK en leverden een kwaadaardige, verlaagde payload. Omdat de compromittering plaatsvond op de DNS-laag, omzeilde deze methode standaard perimeterbeveiliging en server-side bescherming.
De voornaamste forensische indicator: een stille versieverlaging
Omdat de aanvallers DNS beheersten, hoefden ze de kernlogica van de AppsFlyer SDK niet te wijzigen — ze gebruikten die alleen om hun payload te leveren.
Het duidelijkste teken van manipulatie was een stille versieverlaging. De baseline-SDK vóór het incident was versie 0.0.60 (hash 7dbae31c...). Tijdens de aanval werd de versie die vanaf het officiële eindpunt werd geserveerd teruggedraaid naar 0.0.59 (hash db0c4f61...). Legitieme updates draaien versienummers niet terug, wat dit tot duidelijk bewijs van manipulatie maakt.
Door de schone en verlaagde SDK's te vergelijken werden drie gewijzigde regels geïdentificeerd. De aanvallers verwijderden specifieke banner-eindpunten en wijzigden de interne versiestring.
// Schone SDK (0.0.60)
VERSION:"0.0.60"
banner.appsflyer.com/
banner.appsflyer.com/sb/
dismissInjectPixel // aanwezig in schone build
// Gecompromitteerde SDK (0.0.59)
VERSION:"0.0.59"
banner.appsflyer.com/ // .sb/-eindpunt verwijderd
// dismissInjectPixel-functie verwijderd
De aanvallers vermeden het wijzigen van fvalid.appsflyer[.]com of wa.appsflyer[.]com/events, wat Subresource Integrity-controles zou hebben verbroken. In plaats daarvan gebruikten ze de DNS-kaping om al het appsflyer.com-verkeer via hun infrastructuur te routeren, waar de kwaadaardige payloads werden geserveerd.
Na de aanval verplaatste AppsFlyer zijn infrastructuur naar appsflyersdk[.]com en bracht een schone 0.0.61-build uit op dat domein. Het domein appsflyersdk[.]com, geregistreerd in augustus 2019, is eigendom van AppsFlyer.
Deobfuscatie van de polymorfe payloads
Verkeer dat via de gecompromitteerde servers werd gerouteerd, droeg de crypto-stelende payload. Analyse van drie kwaadaardige bestanden onthulde een polymorfe deploymentaanpak met twee obfuscatieschema's gericht op afzonderlijke uitvoeringsomgevingen.
Buildtype 1: de browserpayload (c7adfa8e)
De eerste payload, ongeveer 170 KB groot, draait in de globale window-scope van de browser. Hij gebruikt aangepaste base91-codering met een alfabet van 83 tekens om een stringtabel van 786 items tijdens runtime te decoderen.
In een sandbox vervangt deze payload window.fetch en registreert een MutationObserver om de DOM te scannen op cryptocurrency-adressen. Hij voegt ook een intern module genaamd NetHooksmith toe aan het window-object (window.lIXMkR.NetHooksmith).
Buildtype 2: de Node.js-wrappers (87e46457 & 9b0fac22)
De tweede variant, gevonden in twee builds van elk ongeveer 250 KB, gebruikt een andere obfuscatietechniek gericht op serveromgevingen. In plaats van base91 sluiten deze bestanden kernlogica in geneste Function()-constructors in en decoderen strings via een roterende constante array gecombineerd met String.fromCodePoint.
Deze wrappers gebruiken getter-objecten om in te haken op Node.js-contexten: bijvoorbeeld get GKSDgsL(){return global} en get F1t0ak(){return exports}. Node.js-applicaties, SSR-frameworks en build-pipelines die de SDK via npm of bundlers importeerden, waren kwetsbaar.
Door fromCodePoint-aanroepen te onderscheppen tijdens sandbox-uitvoering werden de gedecodeerde strings verkregen. Deze bevestigden dat de wrappers dezelfde kern-fetch-vervangingslogica uitvoerden, maar aparte walletadressen gebruikten, wat wijst op toegewijde infrastructuur voor server-side compromittering.
De twee walletclusters en C2-infrastructuur
Sandbox-analyse identificeerde twee afzonderlijke walletclusters van de aanvaller. De browserpayload (buildtype 1) bevatte één set adressen en de Node.js-payloads (buildtype 2) een andere. Beide sloegen deze op in een globaal walletAddresses-object.
Cluster 1 (browserpayload 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)-eindpunten
De payloads communiceerden met twee C2-eindpunten op de gekaapte infrastructuur:
https://websdk[.]appsflyer[.]com/v1/api/plugin— haalde nieuwe walletadressen op bij initialisatie.https://websdk[.]appsflyer[.]com/v1/api/process— uploadde geëxfiltreerde walletadressen en metadata via een?rd=-queryparameter met XOR-geobfusceerde data.
Gedragssignaturen en detectie
Omdat de aanvallers obfuscatieschema's en walletadressen rouleerden, waren statische signatures zoals YARA-regels ineffectief. Het gedrag van de payloads is echter consistent en kan worden gedetecteerd.
Beveiligingsteams moeten letten op de volgende indicatoren:
- Console-uitvoer: Alle payloads printen "Generating new wallets..." naar de console tijdens initialisatie.
fetch-vervanging: De payload overschrijft de nativefetchAPI om uitgaande verzoeken met cryptocurrency-adressen te onderscheppen.- Vervuiling van globale objecten: De payload maakt een globaal
walletAddresses-object aan; de browservariant voegtwindow.lIXMkR.NetHooksmithtoe. - Console-onderdrukking: De browserpayload gebruikt 32 verwijzingen naar
console-methoden om waarschuwingen en fouten te verbergen. - DOM-mutatietracking: De browserpayload registreert een
MutationObserverom nieuwe DOM-elementen te scannen op patronen van cryptocurrency-adressen.
Voorbij het incident: het fingerprinting-oppervlak van de legitieme SDK
Onderzoek van de schone SDK (hash 7dbae31c) onthulde dat de legitieme AppsFlyer PBA-plugin uitgebreide apparaat-fingerprinting-data verzamelde, waaronder canvas-fontcontroles, advertentieblokkerdetectie, botdetectie en toegang tot localStorage, sessionStorage en indexedDB.
De SDK laadt ook aanvullende code van fvalid.appsflyer[.]com/af/cp.sdk.1.2.7.js tijdens runtime. Hoewel gebruikelijk in marketing-SDK's, vormt dit een voortdurend supply-chain-risico. Organisaties moeten de noodzaak van dergelijke tracking beoordelen en strikte Content Security Policies (CSP) en Subresource Integrity (SRI) toepassen op alle externe code.
Hoe cside had kunnen helpen
Een DNS-kaping op registrar-niveau omzeilt perimeterbeveiliging en statische analyse. De client-side beveiligingsaanpak van cside detecteert en blokkeert dergelijke aanvallen in realtime via de volgende mechanismen:
- Gedragsafwijkingsdetectie: cside monitort scriptacties in plaats van statische signatures en waarschuwt bij pogingen om
window.fetchte overschrijven of toegang te krijgen tot cryptocurrency-invoervelden. - Blokkering van netwerkexfiltratie: Als de payload wordt uitgevoerd, kunnen de netwerkcontroles van cside uitgaande verbindingen naar C2-servers blokkeren, waardoor het ophalen van wallets en gegevensdiefstal worden voorkomen.
- Waarschuwingen bij hashrotatie: De telemetrie van cside detecteerde afwisselende scripthashes dagen voordat de aanval publiek werd, wat vroegtijdig onderzoek mogelijk maakte.
- Detectie van versieverlaging: cside registreert exacte versies en hashes van externe scripts. Een stille verlaging van
v0.0.60naarv0.0.59zou direct een manipulatiewaarschuwing activeren.
Door zero-trust-maatregelen aan de client-side toe te passen, voorkomt cside dat gecompromitteerde leveranciersscripts misbruik maken van het vertrouwen van gebruikers.
Indicatoren van compromittering (IOC's)
- Domein:
appsflyer[.]com— Legitiem domein gekaapt op registrar-niveau - Nameserver:
ns1.gcorelabs.net— Door aanvaller beheerde nameserver tijdens de kaping - URL (C2):
https://websdk[.]appsflyer[.]com/v1/api/plugin— C2-eindpunt van payload (walletrotatie) - URL (C2):
https://websdk[.]appsflyer[.]com/v1/api/process— C2-eindpunt van payload (exfiltratie) - URL-parameter:
?rd=— Bevat XOR-geobfusceerde exfiltratiedata - Wallet (ETH):
0x1C069d0c73087D0Bae687a6f74a807350dCe1829— Cluster 1 (browserpayload) - Wallet (BTC):
bc1qr7ngtnsh66demm4vzt4kmqxkqj8sqprnuklalt— Cluster 1 (browserpayload) - Wallet (SOL):
4LJi6mAczxZWbUvbMEk5scKhUZNPvfMDTjaVADkPFSsK— Cluster 1 (browserpayload) - Wallet (ETH):
0x782B93e52e62F25Bd002eeAA813B5A3fe49C9558— Cluster 2 (Node.js-wrappers) - Console-string: "Generating new wallets..." — Plaintext-uitvoer door alle payloads
- Globaal object:
walletAddresses— Geïnjecteerd door alle payloadvarianten - Globaal object:
window.lIXMkR.NetHooksmith— Geïnjecteerd door browserpayload - Versiestring:
0.0.59— Verlaagde SDK-versie die op manipulatie wijst
Aanbevelingen
- Vergelijk onmiddellijk de SDK-versie en hash die worden geserveerd vanaf AppsFlyer-eindpunten die u gebruikt met bekende goede hashes; behandel stille verlagingen als hoge-prioriteit manipulatiewaarschuwingen.
- Blokkeer of sinkhole uitgaande verzoeken naar de geïdentificeerde C2-eindpunten en bijbehorende nameservers totdat het herstel is voltooid.
- Versterk CSP en pas SRI toe voor externe resources waar mogelijk; overweeg kritieke leveranciersscripts zelf te hosten na verificatie van de integriteit.
- Scan server-side build-pipelines en SSR-deployments op de hierboven beschreven Node.js-wrapper-indicatoren en roteer eventueel getroffen inloggegevens.
- Implementeer cside om te waken voor API-overschrijvingen (zoals
fetch) en DOM-mutatiescannen door externe scripts.
Dit incident staat niet op zichzelf. Voor een diepgaandere blik op hoe infrastructure laundering de dreiging verder uitbreidt dan de compromittering van één enkele leverancier, zie onze analyse van de gesanctioneerde polyfill-infrastructuur.
Forensische details, bestandshashes en aanvullende telemetrie zijn op verzoek beschikbaar voor getroffen organisaties en incident responders.
Opmerking: Dit artikel vat bevindingen samen uit de Script Insights-telemetrie en sandbox-analyse van cside. Sommige specifieke domeinen en aanvullende IOC's worden achtergehouden terwijl getroffen partijen herstelmaatregelen treffen.





