bee-js ist die JavaScript-Bibliothek, auf der sowohl Swarm Desktop als auch das Kommandozeilenwerkzeug swarm-cli aufbauen. Swarm Desktop betreibt einen Swarm-Knoten auf dem Rechner des Nutzers und legt dort auch die privaten Schlüssel des Knotens ab. Die Projektverantwortlichen haben noch am selben Tag eine bereinigte Version von Swarm Desktop bereitgestellt. Gestohlene Gelder waren bis zuletzt nicht gemeldet.
Zeitfenster und Verbreitung
bee-js 13.3.0 war rund 75 Minuten lang, von 00:09 bis 01:25 Uhr UTC, die aktuelle Version auf npm. Der Schadcode steckt in einem postinstall-Skript, das npm bei der Installation automatisch ausführt, sofern Installationsskripte nicht deaktiviert sind. Ein Projekt musste die Bibliothek also gar nicht importieren, damit der Code lief. Die projekteigenen Pakete swarm-cli und bee-dashboard sowie der Quellcode von Swarm Desktop ließen Versionsbereiche zu, die 13.3.0 einschlossen – eine frische Installation in diesem Zeitraum konnte die manipulierte Version also nachziehen.
Swarm Desktop 0.56.2 erschien gegen 00:36 Uhr UTC auf GitHub und wurde rund achteinhalb Stunden später zurückgezogen. Nach einer Vorfallsanalyse des Lieferketten-Sicherheitsunternehmens Socket konnte der eingebaute Updater die Version Windows-Rechnern mit x64-Architektur und Macs mit Apple Silicon innerhalb von etwa zehn Minuten anbieten. Intel-Macs wurde sie nie angeboten, Linux-Installationen aktualisieren sich nicht automatisch.
Eine Zahl infizierter Rechner nennt keine der Analysen. Socket schätzt grob, dass bee-js 13.3.0 etwa zehnmal heruntergeladen wurde, Sicherheitsscanner und Spiegelserver eingeschlossen. Swarm Desktop 0.56.2 kam bis 08:27 Uhr UTC auf 65 Downloads, darunter solche von Sicherheitsforschern.
Reaktion der Entwickler
Die Ethersphere-Maintainer ersetzten 0.56.2 durch Version 0.56.3. In der Änderung, mit der die neue Version eingerichtet wurde, schrieb einer von ihnen, 0.56.2 sei „von einem Angreifer mit gestohlenen CI-Zugangsdaten veröffentlicht und zurückgezogen worden“. Laut seiner Vorfallsnotiz entspricht 0.56.3 inhaltlich der Vorversion 0.56.1, ist aber mit einem neu ausgestellten Developer-ID-Zertifikat signiert. Der Auto-Updater soll Installationen von 0.56.2 auf die neue Version heben; Linux-Pakete müssen von Hand ersetzt werden. Ein Vergleich des Quellcodes beider Versionen ergab außer der Versionsnummer und den Release Notes keine Unterschiede. Auf npm ist inzwischen wieder 13.2.0 die aktuelle bee-js-Version, 13.3.0 lässt sich nicht mehr aus der Registry laden.
Empfohlene Maßnahmen
Die GitHub-Sicherheitsmeldung zu bee-js 13.3.0 hält fest: „Jeder Rechner, auf dem dieses Paket installiert ist oder läuft, sollte als vollständig kompromittiert gelten.“ Das Software-Lieferketten-Sicherheitsunternehmen SafeDep rät dasselbe für jeden Rechner, auf dem Swarm Desktop 0.56.2 installiert war.
Für Projekte und CI-Jobs mit bee-js gilt:
- Lockfiles, Paket-Caches, interne Registries und CI-Installationsprotokolle nach @ethersphere/bee-js@13.3.0 durchsuchen, auch nach Kopien, die über andere Pakete eingebunden wurden.
- Version 13.2.0 festschreiben und zwischengespeicherte Kopien von 13.3.0 löschen, auch auf genutzten npm-Spiegeln.
- Wurde 13.3.0 mit aktivierten Installationsskripten installiert, den Rechner oder CI-Runner als kompromittiert behandeln – auch wenn das Protokoll keine Fehler zeigt, denn der Code unterdrückt seine eigenen Netzwerkfehler.
- Von einem sauberen Rechner aus alle Passwörter, Tokens und Schlüssel erneuern, auf die der installierende Nutzer oder CI-Job Zugriff hatte.
Für Nutzer von Swarm Desktop gilt:
- In der Logdatei bee-desktop.log nach der Zeile „Bee Desktop version: 0.56.2 (production)“ suchen. Sie wird bei jedem Start geschrieben, unmittelbar bevor der Schadcode läuft. Der Log-Ordner liegt unter macOS in ~/Library/Logs/Swarm Desktop/, unter Windows in %LOCALAPPDATA%\Swarm Desktop\Log\ und unter Linux in ~/.local/state/Swarm Desktop/.
- Version 0.56.3 installieren, unter Linux das Paket manuell ersetzen.
- Lief 0.56.2 jemals, Schlüssel und Passwort des Knotens als gestohlen betrachten und von einem sauberen Rechner aus Guthaben, Chequebook und Stake des Knotens auf einen neuen Schlüssel übertragen.
Auf allen Rechnern, auf denen der Code ausgeführt wurde, sind der Ordner ~/.solidity/, unter Linux der Nutzerdienst solidity-langsupport-runner.service, unter macOS der LaunchAgent com.solidity.langsupport.runner und unter Windows der Dienst „ScreenConnect Client (5cbe79c9c25524df)“ zu entfernen. Ein Update, eine Neuinstallation oder das Entfernen von App oder Paket beseitigt diese Komponenten nicht. Wo möglich, sollte der Rechner aus einem vertrauenswürdigen Image neu aufgesetzt statt bereinigt werden.
Funktionsweise der Schadsoftware
Nach der technischen Analyse von SafeDep enthalten beide Releases denselben Loader: wenige Codezeilen, die weiteren Code von api.frameworkmetrics[.]xyz herunterladen und mit den Rechten des Nutzers ausführen. In bee-js ist der Loader das postinstall-Skript, in Swarm Desktop läuft er bei jedem App-Start. Der nachgeladene Code sucht im Datenordner von Swarm Desktop nach config.yaml und data-dir/keys/swarm.key und schickt beide Dateien, sofern vorhanden, an den Server der Angreifer. Die Schlüsseldatei ist zwar ein verschlüsselter Ethereum-Keystore, Swarm Desktop speichert das zugehörige Passwort aber im Klartext in config.yaml. Mit beiden Dateien können die Angreifer laut SafeDep die xDAI- und xBZZ-Token des Knoten-Wallets, das Chequebook-Guthaben und den Stake abziehen.
Zusätzlich installiert der Code eine Hintertür. Unter Linux und macOS ist das eine in Go geschriebene Remote-Shell namens evjawbreaker, die im versteckten Ordner ~/.solidity liegt und unter Linux als Nutzerdienst, unter macOS als LaunchAgent im Hintergrund läuft. Die Adresse ihres Steuerservers liest sie aus einem Ethereum-Smart-Contract, sodass die Angreifer sie jederzeit ändern können. Aktualisiert hatten sie diese Adresse 29 Minuten bevor der Schadcode in bee-js eingefügt wurde.
Unter Windows installiert der Code einen echten, vom Hersteller ConnectWise signierten ScreenConnect-Fernwartungsclient, der als Systemdienst läuft und sich mit dem Relay der Angreifer verbindet. Ist der Nutzer Administrator, verschafft sich der Code über eine bekannte Umgehung der Benutzerkontensteuerung Administratorrechte; andernfalls zeigt er die UAC-Abfrage erneut an, sobald der Nutzer sie abbricht. Mit diesen Rechten legt er eine Ausnahme in Microsoft Defender an und installiert den Client unbemerkt.
Wie die Releases veröffentlicht wurden
Beide Veröffentlichungen stammen vom Konto bee-worker, das Ethersphere für automatisierte Releases nutzt. Keine der Änderungen war signiert oder über einen Pull Request eingereicht. Für bee-js legten die Angreifer ein GitHub-Release für die neue Version an, was den npm-Veröffentlichungs-Workflow des Projekts auslöste. Dieser benötigte keine Freigabe und publizierte das Paket laut Socket binnen 73 Sekunden. Weil der echte Workflow des Projekts das Paket baute, trug es gültige Provenance-Angaben – also den Nachweis, der ein npm-Paket mit Repository und Build-Workflow verknüpft. Provenance belegt allerdings nur, wo ein Paket gebaut wurde, nicht, ob jemand den Code geprüft hat.
Für Swarm Desktop starteten die Angreifer manuell einen Build-Workflow, der Zugriff auf die Apple- und Windows-Signaturzertifikate des Projekts hatte und ebenfalls ohne Freigabe lief. Die macOS-App war nach Erkenntnissen von Socket mit der Developer ID des Projekts signiert und von Apple notarisiert, sodass macOS lediglich die übliche Abfrage beim ersten Start zeigte. Die Maintainer haben die Signierjobs inzwischen so umgestellt, dass sie eine Freigabe durch das DevOps-Team des Projekts benötigen und nur noch vom Main-Branch aus laufen.
Wie die Angreifer Zugang erlangten, ist offen. Die Vorfallsnotiz des Maintainers nennt den Diebstahl von CI-Zugangsdaten und Secrets als Ursache. Socket zufolge wurden zwei GitHub-Konten genutzt: bee-worker und das Konto eines langjährigen Maintainers. Wie die Zugangsdaten entwendet wurden, erklärt keine der Analysen.
Verbindung zu früheren Angriffen
Die Payloads teilen sich einen Ethereum-Contract, ein ScreenConnect-Relay und Dateinamen mit gefälschten Erweiterungen für Solidity-Entwickler, die im September auf dem Marktplatz Open VSX auftauchten. Forscher von Pluto Security beschrieben diese Erweiterungen in ihrer EtherDuck-Analyse vom 1. Oktober und ordnen sie „mit hoher Sicherheit“ der Gruppe hinter der ursprünglichen SleepyDuck-Erweiterung zu, die 2025 ihre Serveradresse aus einem anderen Ethereum-Contract bezog. Socket schreibt auch die manipulierten bee-js- und Swarm-Desktop-Versionen dieser Gruppe zu.
Indikatoren für eine Kompromittierung
- Domain: api.frameworkmetrics[.]xyz
- URL-Pfad: /v1/analytics (bee-js-Loader)
- URL-Pfad: /v1/electron (Swarm-Desktop-Loader)
- URL-Pfad: /v1/assets/ (weitere Payloads)
- URL-Pfad: /v1/swarm/report (gestohlene Wallet-Dateien)
- HTTP-Header: X-Ethersphere: 1
- IP:Port: 193[.]57[.]9[.]155:4912 (Steuerserver von evjawbreaker)
- IP:Port: 185[.]232[.]84[.]169:8041 (ScreenConnect-Relay)
- Ethereum-Contract: 0xf8a900Db50b3331be6B768bA460BB59f3E40C344
- Pfad: ~/.solidity/
- systemd-Unit: solidity-langsupport-runner.service
- LaunchAgent: com.solidity.langsupport.runner
- Dienst: ScreenConnect Client (5cbe79c9c25524df)
- SHA-256: 9b73e7cd4e1425e770392549d8df46c706139ef476f4f7b9ac405165dc8d9696 (linux_amd64)
- SHA-256: b601776817363b96295119f7221338a122d5247a35a77a64b04f286e1bbcc565 (linux_arm64)
- SHA-256: 80d2672e2599732d3c0ae2a4cd0d1e3fe4d555a60273ce33feb99db3f34d250f (darwin_amd64)
- SHA-256: fae61f31f00988fdc5cc9e7272b51e08af2e245d81003237875415930fd27358 (darwin_arm64)
- SHA-256: 37d14bff30762ca701e9c1f8bc6c57c065bb20ae3a2208cb7411a6530610f08e (invoke.ps1)
- SHA-256: 7527e86d70e7c9493db4356f1c3775380431b310000f2602c1e993cf435d01da (app.msi)
