Elastic Security Labs hat erste Triage- und Erkennungsregeln für die Axios-Lieferkettenkompromittierung veröffentlicht. Dies ist eine detaillierte Analyse der Funkzugangstechnologie und der Nutzlasten.
Einführung
Elastic Security Labs hat eine Gefährdung der Lieferkette des axios npm-Pakets festgestellt, eines der meistgenutzten Pakete im JavaScript-Ökosystem mit etwa 100 Millionen wöchentlichen Downloads. Der Angreifer kompromittierte ein Wartungskonto und veröffentlichte mit einer Hintertür versehene Versionen, die über einen bösartigen Postinstall-Hook einen plattformübergreifenden Remote-Access-Trojaner auf macOS-, Windows- und Linux-Systemen einschleusten.
Wichtigste Erkenntnisse
- Ein kompromittiertes npm-Maintainer-Konto (jasonsaayman) wurde verwendet, um zwei schädliche Versionen des weit verbreiteten Axios-HTTP-Clients zu veröffentlichen – 1.14.1 (als „latest“ gekennzeichnet) und 0.30.4 (als „legacy“ gekennzeichnet) – was bedeutet, dass ein standardmäßiges „npm install axios“ zu einem Paket mit Hintertür führte.
- Das bösartige JavaScript installiert plattformspezifische Stage-2-Implantate für macOS, Windows und Linux.
- Alle drei Stage-2-Payloads sind Implementierungen desselben RAT – identisches C2-Protokoll, Befehlssatz, Beacon-Kadenz und gefälschter User-Agent, geschrieben in PowerShell (Windows), C++ (macOS) und Python (Linux).
- Der Dropper führt eine forensische Bereinigung durch, indem er sich selbst löscht und seine package.json-Datei durch eine saubere Kopie ersetzt, wodurch Spuren des Postinstall-Triggers beseitigt werden.
node_modules
Präambel
Am 30 März 2026 entdeckte Elastic Security Labs durch automatisierte Lieferkettenüberwachung eine Kompromittierung der Lieferkette, die auf das axios npm-Paket abzielte. Der Angreifer erlangte die Kontrolle über den npm-Account von jasonsaayman, einem der Hauptverantwortlichen des Projekts, und veröffentlichte innerhalb von 39 Minuten zwei Versionen mit Hintertüren.
Das axios-Paket ist eine der am weitesten verbreiteten HTTP-Client-Bibliotheken im JavaScript-Ökosystem. Zum Zeitpunkt der Entdeckung wiesen sowohl die neuesten als auch die älteren Dist-Tags auf kompromittierte Versionen hin, sodass die Mehrheit der Neuinstallationen eine Version mit Hintertür erhielt.
Die bösartigen Versionen führten eine einzige neue Abhängigkeit ein: plain-crypto-js, ein eigens dafür entwickeltes Paket, dessen Postinstall-Hook stillschweigend plattformspezifische Stage-2-RAT-Implantate von sfrclak[.]com:8000 herunterlud und ausführte.
Was diese Kampagne über ihren Wirkungsradius hinaus bemerkenswert macht, ist die Werkzeugausstattung der zweiten Phase. Der Angreifer setzte drei parallele Implementierungen desselben RAT ein – jeweils eine für Windows, macOS und Linux –, die alle ein identisches C2-Protokoll, eine identische Befehlsstruktur und ein identisches Beacon-Verhalten aufwiesen. Es handelt sich hierbei nicht um drei verschiedene Tools, sondern um ein einziges plattformübergreifendes Implantat-Framework mit plattformspezifischen Implementierungen.
Elastic Security Labs hat am 31. März 2026 um 01:50 Uhr UTC eine Sicherheitswarnung auf GitHub für das axios-Repository eingereicht, um die Offenlegung zu koordinieren und sicherzustellen, dass die Maintainer und die npm-Registry auf die kompromittierten Versionen reagieren können.
Nachdem die Community den Sicherheitsverstoß in den sozialen Medien gemeldet hatte, veröffentlichte Elastic Security Labs erste Erkenntnisse, um den Verteidigern eine Reaktion in Echtzeit zu ermöglichen.
Dieser Beitrag behandelt die gesamte Angriffskette: von der Kompromittierung der Lieferkette auf npm-Ebene über den verschleierten Dropper bis hin zur Architektur des plattformübergreifenden RAT und den wesentlichen Unterschieden zwischen seinen drei Varianten.
Kampagnenübersicht
Der Kompromiss wird in den Metadaten der npm-Registry deutlich. Die E-Mail-Adresse des Maintainers änderte sich von jasonsaayman@gmail[.]com – die bei allen vorherigen legitimen Versionen vorhanden war – zu ifstap@proton[.]me bei den bösartigen Versionen. Auch die Veröffentlichungsmethode änderte sich:
| Version | Herausgegeben von | Method | Herkunft |
|---|---|---|---|
axios@1.14.0 (legitim) | jasonsaayman@gmail[.]com | GitHub Actions OIDC | SLSA-Herkunftsnachweise |
axios@1.14.1 (kompromittiert) | ifstap@proton[.]me | Direkte CLI-Veröffentlichung | Kein Schutz |
axios@0.30.4 (kompromittiert) | ifstap@proton[.]me | Direkte CLI-Veröffentlichung | Kein Schutz |
Der Wechsel von einem vertrauenswürdigen OIDC-Publisher-Flow mit SLSA-Provenienz zu einem direkten CLI-Publish mit geänderter E-Mail-Adresse ist ein klares Indiz für unautorisierten Zugriff.
Zeitleiste
- 2026-02-18 17:19 UTC —
axios@0.30.3rechtmäßig veröffentlicht vonjasonsaayman@gmail[.]com - 2026-03-27 19:01 UTC —
axios@1.14.0Rechtmäßig veröffentlicht über GitHub Actions OIDC - 2026-03-30 05:57 UTC —
plain-crypto-js@4.2.0veröffentlicht vonnrwise(nrwise@proton.me) — Bereinigen des Köders zum Aufbau des Registrierungsverlaufs - 30.03.2026 23:59 UTC —
plain-crypto-js@4.2.1veröffentlicht vonnrwise— bösartige Version mitpostinstallHintertür - 2026-03-31 00:21 UTC —
axios@1.14.1veröffentlicht von einem kompromittierten Konto — markiert mitlatest - 2026-03-31 01:00 UTC —
axios@0.30.4veröffentlicht von einem kompromittierten Konto — markiert mitlegacy
Betroffene Pakete
axios@1.14.1— Böswillig, zum Zeitpunkt der Entdeckung mitlatestgekennzeichnetaxios@0.30.4— Böswillig, zum Zeitpunkt der Entdeckung mitlegacygekennzeichnetplain-crypto-js@4.2.0— Saubere Täuschung, veröffentlicht, um die Registerhistorie aufzubauenplain-crypto-js@4.2.1— Böswilliges Nutzlasttransportfahrzeug (postinstallHintertür)
Sichere Versionen: axios@1.14.0 (letzte legitime 1.x-Version mit SLSA-Herkunft) und axios@0.30.3 (letzte legitime 0.30.x -Version).
Der Angreifer markierte sowohl die neuesten als auch die älteren Kanäle und maximierte so den Wirkungsradius über Projekte hinweg, die entweder die aktuelle oder die ältere Axios-API verwendeten.
Code-Analyse
Phase 1: Der Plain-Crypto-JS-Dropper
Die gesamte Auslieferungskette hängt vom Postinstall-Lifecycle-Hook von npm ab. Die Installation einer der beiden kompromittierten Axios-Versionen zieht plain-crypto-js@^4.2.1 als Abhängigkeit nach sich, welche Folgendes deklariert:
"scripts": {
"postinstall": "node setup.js"
}
Dies bewirkt, dass setup.js während npm install automatisch ausgeführt wird – eine Benutzerinteraktion ist nicht erforderlich.
Die setup.js-Datei verwendet ein zweischichtiges Kodierungsschema, um ihr Verhalten zu verbergen:
- Schicht 1: Stringumkehrung gefolgt von Base64-Dekodierung
- Schicht 2: XOR-Verschlüsselung mit dem Schlüssel OrDeR_7077 und einem positionsabhängigen Index (7 * i² % 10)
Alle kritischen Zeichenketten, Modulnamen, URLs und Shell-Befehle werden in einem kodierten Array stq[] gespeichert und zur Laufzeit dekodiert. Die entschlüsselten Inhalte offenbaren die operative Infrastruktur:
Plattformspezifische Auslieferung
Nach dem Dekodieren seiner Stringtabelle prüft der Dropper os.platform() und verzweigt sich in eine von drei Zustellungsroutinen. Jeder sendet einen HTTP-POST-Request an http://sfrclak[.]com:8000/6202033 mit einem plattformspezifischen Body — packages.npm.org/product0 (macOS), packages.npm.org/product1 (Windows), packages.npm.org/product2 (Linux) — ermöglicht es dem C2-Server, die korrekte Nutzlast von einem einzigen Endpunkt aus zu liefern. Die packages.npm.org/ Das Präfix ist ein bewusster Versuch, ausgehenden Datenverkehr in Netzwerkprotokollen als harmlose npm-Registry-Kommunikation erscheinen zu lassen:
| Plattform | Liefermethode | Standort Phase 2 | Verkleidung |
|---|---|---|---|
| macOS | AppleScript lädt über osascript eine Binärdatei mit curl herunter. | /Library/Caches/com.apple.act.mond | Apple-Systemdaemon |
| Windows | VBScript-Downloads .ps1 via curl, ausgeführt über umbenanntes PowerShell (%PROGRAMDATA%\wt.exe) | %TEMP%\6202033.ps1 (vorübergehend) | Windows Terminal |
| Linux | Direkter curl-Download und Python3-Ausführung | /tmp/ld.py | Kein Schutz |
Anti-Forensik
Die Pipette führt zwei Aufräumaktionen durch:
- Selbstlöschung: setup.js entfernt sich selbst mittels fs.unlink(__filename)
- Paketmanifest-Tausch: Eine saubere Datei namens package.md (die eine unproblematische Versionskonfiguration 4.2.0 ohne Postinstall-Hook enthält) wird in package.json umbenannt. die schädliche Version überschreiben
Eine nach dem Vorfall durchgeführte Überprüfung der Datei node_modules/plain-crypto-js/package.json ergab keine Hinweise auf den Postinstall-Trigger. Die schädliche setup.js-Datei ist verschwunden. Lediglich die Sperrdatei und die npm-Audit-Logs enthalten noch Beweise.
Phase 2: Plattformübergreifende RAT
Die drei Stage-2-Payloads: PowerShell für Windows, kompiliertes C++ für macOS und Python für Linux sind keine drei verschiedenen Tools. Es handelt sich um drei Implementierungen derselben RAT-Spezifikation, die ein identisches C2-Protokoll, einen identischen Befehlssatz, ein identisches Nachrichtenformat und ein identisches Betriebsverhalten aufweisen. Die Konsistenz deutet stark darauf hin, dass es sich um einen einzelnen Entwickler oder ein eng abgestimmtes Team handelt, das mit einem gemeinsamen Designdokument arbeitet.
Gemeinsame Architektur
Folgende Eigenschaften sind bei allen drei Varianten identisch:
- C2-Transport: HTTP POST
- Body-Kodierung: Base64-kodiertes JSON
- User-Agent:
mozilla/4.0 (compatible; msie 8.0; windows nt 5.1; trident/4.0) - Beacon-Intervall: 60 Sekunden
- Sitzungs-UID: 16-stellige zufällige alphanumerische Zeichenfolge, die pro Ausführung generiert wird
- Ausgehende Nachrichtentypen:
FirstInfo,BaseInfo,CmdResult - Eingehende Befehlstypen:
kill,peinject,runscript,rundir - Antwortbefehlstypen:
rsp_kill,rsp_peinject,rsp_runscript,rsp_rundir
Besonders auffällig ist die gefälschte User-Agent-Zeichenfolge für IE8/Windows XP; sie ist auf allen drei Plattformen anachronistisch, und ihr Vorhandensein auf einem macOS- oder Linux-Host ist ein starkes Erkennungsmerkmal.
Initialisierung und Aufklärung
Beim Startvorgang jeder Variante:
- Generiert eine Sitzungs-UID – 16 zufällige alphanumerische Zeichen, die in jede nachfolgende C2-Nachricht eingefügt wird.
- Erkennt Betriebssystem und Architektur – meldet plattformspezifische Kennungen (z. B. windows_x64, macOS, linux_x64)
- Listet die relevanten Anfangsverzeichnisse auf (Benutzerprofil, Dokumente, Desktop, Konfigurationsverzeichnisse)
- Sendet ein FirstInfo-Beacon mit der UID, der Betriebssystemkennung und dem Verzeichnis-Snapshot.
Nach der Initialisierung tritt das Implantat in den Hauptkreislauf ein. Der erste BaseInfo-Heartbeat enthält ein umfassendes Systemprofil. Auf allen Plattformen werden dieselben Datenkategorien erfasst, obwohl sich die zugrunde liegenden APIs unterscheiden:
| Gesammelte Daten | Windows-Quelle | macOS-Quelle | Linux-Quellcode |
|---|---|---|---|
| Hostname | %COMPUTERNAME% Umgebungsvariable | gethostname() | /proc/sys/kernel/hostname |
| Nutzername | %USERNAME% Umgebungsvariable | getuid() + getpwuid() | os.getlogin() |
| Version des Betriebssystems | WMI / Registrierung | sysctlbyname("kern.osproductversion") | platform.system() + platform.release() |
| Zeitzone | Systemzeitzone | localtime_r() | datetime.timezone |
| Bootzeit | Systemverfügbarkeit | sysctl("kern.boottime") | /proc/uptime |
| Installationsdatum | Registry / WMI | stat("/") oder sysctl | Zeitstempel von /var/log/installer oder /var/log/dpkg.log |
| Hardwaremodell | WMI | sysctlbyname("hw.model") | /sys/class/dmi/id/product_name |
| CPU-Typ | WMI | sysctlbyname() | platform.machine() |
| Process list | Vollständige Prozess-ID, Sitzung, Name, Pfad | popen("ps") (bis zu 1000) | Vollständige /proc-Aufzählung (PID, PPID, Benutzer, Befehlszeile) |
Die nachfolgenden Herzschläge sind leicht und enthalten lediglich einen Zeitstempel, um zu bestätigen, dass das Implantat funktioniert.
Befehlsausgabe
Die C2-Antwort wird als JSON analysiert, und das Feld „type“ bestimmt die auszuführende Aktion. Alle drei Varianten implementieren dieselben vier Befehle:
kill — Selbstbeendigung. Sendet eine rsp_kill-Bestätigung und beendet sich. Der Persistenzmechanismus der Windows-Variante (Registry-Schlüssel + Batch-Datei) bleibt nach dem Kill-Befehl erhalten, sofern er nicht explizit gelöscht wird; die macOS- und Linux-Varianten verfügen über keinen eigenen Persistenzmechanismus.
runscript — Skript-/Befehlsausführung. Der primäre Interaktionsbefehl des Bedieners. Akzeptiert ein Script-Feld (auszuführender Code) und ein Param-Feld (Argumente). Wenn das Skript leer ist, wird der Parameter direkt als Befehl ausgeführt. Der Ausführungsmechanismus ist plattformnativ:
| Plattform | Ausführungsmechanismus |
|---|---|
| Windows | PowerShell mit -NoProfile -ep Umgehung |
| macOS | AppleScript über /usr/bin/osascript |
| Linux | Shell via subprocess.run(shell=True) oder Python über python3 -c |
peinject – Zustellung binärer Nutzdaten. Trotz der Windows-zentrierten Bezeichnung („PE inject“) implementieren alle drei Plattformen dies als Methode zum Ablegen und Ausführen binärer Nutzdaten:
| Plattform | Implementation |
|---|---|
| Windows | Reflektierendes Laden der .NET-Assembly über [System.Reflection.Assembly]::Load() |
| macOS | Base64-dekodiert und verwirft eine Binärdatei und führt sie mit vom Operator bereitgestellten Parametern aus. |
| Linux | Base64-dekodiert eine Binärdatei nach /tmp/.<random 6-Zeichenkette> (versteckte Datei), startet über subprocess.Popen(). |
Die Windows-Implementierung verfügt über eine In-Memory-Ausführung ohne Dateispeicherung, jedoch ohne AMSI zu deaktivieren, was beim Laden der Assembly sicherlich zu einer Fehlermeldung führen wird. Die macOS- und Linux-Varianten verfolgen den einfacheren Ansatz, eine Binärdatei auf die Festplatte zu schreiben und diese direkt auszuführen.
rundir — Verzeichnisaufzählung. Akzeptiert Pfade und gibt detaillierte Dateilisten zurück (Name, Größe, Typ, Erstellungs-/Änderungszeitstempel, Anzahl der Unterverzeichnisse). Ermöglicht dem Benutzer das interaktive Durchsuchen des Dateisystems.
Zusammenfassung der Fähigkeiten
| Funktionalität | Windows (PowerShell) | macOS (C++) | Linux (Python) |
|---|---|---|---|
| Persistenz | Registry-Schlüssel „Run“ + versteckte .bat-Datei | Kein Schutz | Kein Schutz |
| Skriptausführung | PowerShell | AppleScript via osascript | Shell- oder Python-Inline-Code |
| Binäre Injektion | Reflective .NET-Lasteinspeisung in cmd.exe | Binärdatei ablegen + ausführen | Binärdatei nach /tmp/ ablegen + ausführen |
| Anti-Forensik | Bereinigung versteckter Fenster und temporärer Dateien | Versteckte temporäre .scpt-Datei | Versteckte /tmp/.XXXXXX-Dateien |
Quellenangabe
Die über den plain-crypto-js Postinstall-Hook ausgelieferte macOS Mach-O Binärdatei weist erhebliche Überschneidungen mit WAVESHAPER auf, einer von Mandiant verfolgten C++-Backdoor, die UNC1069, einem mit Nordkorea in Verbindung stehenden Bedrohungscluster, zugeordnet wird.
Fazit
Diese Kampagne beweist die anhaltende Attraktivität des npm-Ökosystems als Angriffsvektor für Lieferketten. Durch die Kompromittierung eines einzigen Maintainer-Kontos eines der am häufigsten genutzten Pakete im JavaScript-Ökosystem erlangte der Angreifer einen Verbreitungsmechanismus mit potenzieller Reichweite in Millionen von Umgebungen.
Der zuverlässigste Erkennungsindikator des Toolkits ist gleichzeitig seine kurioseste Designentscheidung: die identische, fest codierte User-Agent-Zeichenfolge für IE8/Windows XP auf allen drei Plattformvarianten. Während es einen konsistenten Protokoll-Fingerabdruck für das serverseitige Routing von C2 liefert, ist es auf jedem modernen Netzwerk trivial erkennbar – und stellt auf macOS- und Linux-Hosts eine sofortige Anomalie dar.
Elastic Security Labs wird diese Aktivitätsgruppe weiterhin überwachen und diesen Beitrag mit allen weiteren Erkenntnissen aktualisieren.
MITRE ATT&CK
Elastic verwendet das MITRE ATT&CK-Framework , um gängige Taktiken, Techniken und Verfahren zu dokumentieren, die von Advanced Persistent Threats gegen Unternehmensnetzwerke eingesetzt werden.
Taktiken
Taktiken stellen das Warum einer Technik oder Untertechnik dar. Es ist das taktische Ziel des Gegners: der Grund für die Ausführung einer Aktion.
Techniken
Techniken stellen dar, wie ein Angreifer ein taktisches Ziel erreicht, indem er eine Aktion ausführt.
- Kompromiss in der Lieferkette: Kompromiss bei Softwareabhängigkeiten
- Befehls- und Skriptinterpreter: JavaScript
- Befehls- und Skriptinterpreter: PowerShell
- Befehls- und Skriptinterpreter: AppleScript
- Command and Scripting Interpreter: Unix Shell
- Command and Scripting Interpreter: Python
- Autostart-Ausführung beim Systemstart oder der Anmeldung: Registrierungsschlüssel
- Verschleierte Dateien oder Informationen
- Maskerade
- Versteckte Dateien und Verzeichnisse
- Prozessinjektion
- Indicator Removal: File Deletion
- Erkennung von Systeminformationen
- Prozess-Erkennung
- Datei- und Verzeichniserkennung
- Application Layer Protocol: Web Protocols
- Nicht standardmäßiger Anschluss
- Datenkodierung: Standardkodierung
- Übergabe von Eingangswerkzeugen
Beobachtungen
Die folgenden Observablen wurden in dieser Studie diskutiert.
| Überwachbar | Typ | Name | Referenz |
|---|---|---|---|
617b67a8e1210e4fc87c92d1d1da45a2f311c08d26e89b12307cf583c900d101 | SHA-256 | 6202033.ps1 | Windows-Nutzlast |
92ff08773995ebc8d55ec4b8e1a225d0d1e51efa4ef88b8849d0071230c9645a | SHA-256 | com.apple.act.mond | MacOS-Nutzlast |
fcb81618bb15edfdedfb638b4c08a2af9cac9ecfa551af135a8402bf980375cf | SHA-256 | ld.py | Linux-Nutzlast |
sfrclak[.]com | Domain | C2 | |
142.11.206[.]73 | IPv4-ADDR | C2 |
Referenzen
In der obigen Studie wurde auf Folgendes Bezug genommen: