Realtime-Attack-Map
SURICATA / LIVE FEED

Axios NPM Hack 2026

Ein bösartiges Update in der Axios-Bibliothek infizierte Millionen Windows/Mac/Linux-Systeme. Das sollte man nicht ignorieren.

Axios NPM Hack 2026

Am 30. und 31. März 2026 wurde das JavaScript-Ökosystem von einem massiven Supply-Chain-Angriff getroffen, als die viel genutzte Bibliothek Axios mit einem plattformübergreifenden Remote Access Trojaner (RAT) infiziert wurde. Durch eine geschickte Verschleierungstaktik löscht die Malware ihre eigenen Spuren unmittelbar nach der Installation, was herkömmliche Überprüfungen des Dateisystems ins Leere laufen lässt. Der folgende Beitrag analysiert die technischen Hintergründe dieser Kompromittierung und liefert ein forensisches Bash-Skript zur vorläufigen Identifikation betroffener Linux-Systeme.

Anatomie der Kompromittierung

Bei fast 100 Millionen wöchentlichen Downloads gleicht eine Schwachstelle im Axios-Paket einem Flächenbrand im Rechenzentrum. Der Angriff begann mit der feindlichen Übernahme des npm-Accounts eines Hauptentwicklers. Dabei wurde die hinterlegte E-Mail-Adresse durch ein anonymes ProtonMail-Konto ersetzt. Kurze Zeit später wurden die manipulierten Versionen axios@1.14.1 und axios@0.30.4 direkt über die Kommandozeile veröffentlicht. Dies umging gezielt die sonst üblichen CI/CD-Sicherheitsmechanismen und OIDC-Signaturen.

Der eigentliche Schadcode befand sich jedoch nicht im Quelltext von Axios selbst. Die Angreifer fügten lediglich eine einzige Zeile in die package.json ein, welche eine neue, harmlose klingende Abhängigkeit namens plain-crypto-js@4.2.1 lud. Dieses Paket enthielt den eigentlichen Dropper. Jeder Entwickler-Rechner und jede Build-Pipeline, die in dem rund dreistündigen Zeitfenster einen ungepinnten npm install-Befehl ausführte, lud sich die Schadsoftware stillschweigend herunter.

Anti Forensik und das Verschwinden der Spuren

Sobald das manipulierte Paket plain-crypto-js heruntergeladen wird, greift ein automatischer postinstall-Hook in der Konfiguration, der im Hintergrund die Datei setup.js ausführt. Diese JavaScript-Datei nutzt eine zweistufige Verschleierung: Zunächst wird ein Base64-String umgekehrt und anschließend mit dem XOR-Schlüssel OrDeR_7077 dechiffriert. Daraus resultiert der eigentliche Befehl zum Herunterladen des Trojaners von der Command-and-Control-Infrastruktur unter sfrclak.com.

Besonders tückisch ist das Verhalten unmittelbar nach der Infektion. Die Datei setup.js löscht sich selbstständig aus dem Dateisystem. Gleichzeitig wird die kompromittierte package.json entfernt und durch eine vorbereitete, völlig harmlose package.md ersetzt, die kurzerhand in package.json umbenannt wird. Wer im Nachgang den Ordner node_modules mit klassischen Antiviren-Scannern oder npm audit untersucht, blickt auf eine vollkommen unauffällige Dateistruktur. Die Malware macht sich unsichtbar, was forensische Analysen drastisch erschwert.

Der Trojaner WAVESHAPER V2 im Detail

Nach erfolgreicher Deobfuscation analysiert das Skript das zugrundeliegende Betriebssystem und lädt eine plattformspezifische Variante der Malware herunter. Analysen von Google Threat Intelligence bringen diese Nutzlast mit einer nordkoreanischen Gruppierung (UNC1069) und deren Backdoor "WAVESHAPER.V2" in Verbindung.

Auf Linux-Systemen wird ein Python-Skript unter /tmp/ld.py abgelegt und im Hintergrund gestartet. Auf Windows-Umgebungen wird das legitime Terminal-Programm kopiert, um unter %PROGRAMDATA%\wt.exe PowerShell-Restriktionen zu umgehen und Ausführungsrichtlinien außer Kraft zu setzen. macOS-Systeme erhalten eine Mach-O-Binärdatei, die sich in /Library/Caches/ als Apple-System-Daemon tarnt. In allen Fällen beginnt der RAT sofort damit, Umgebungsvariablen, SSH-Schlüssel und Cloud-Zugangsdaten (wie AWS- oder NPM-Tokens) aus dem Speicher abzugreifen und an die IP-Adresse 142.11.206.73 oder 23.254.167.216 auszuleiten.

Intrusion-Detection

Falls man ein IDS besitzt, wie zum Beispiel auf einer OPNsense Firewall, kann man folgende Signaturen nutzen:

# 1. Erkennung der DNS-Anfrage an die bekannte C2-Domain
alert dns $HOME_NET any -> any any (msg:"NPM Supply Chain: DNS Query to Axios RAT C2 (sfrclak.com)"; \
    dns.query; content:"sfrclak.com"; nocase; \
    reference:url,socradar.io/blog/axios-npm-supply-chain-attack-2026-ciso-guide/; \
    classtype:trojan-activity; sid:9000101; rev:1;)

# 2. Erkennung von jeglichem ausgehenden Traffic an die harte C2-IP-Adresse
alert ip $HOME_NET any -> 142.11.206.73, 23.254.167.216 any (msg:"NPM Supply Chain: Outbound Traffic to Axios RAT C2 IP"; \
    reference:url,socradar.io/blog/axios-npm-supply-chain-attack-2026-ciso-guide/; \
    classtype:trojan-activity; sid:9000102; rev:1;)

# 3. Erkennung von HTTP/TLS Traffic mit der C2-Domain (SNI Check für TLS)
alert tls $HOME_NET any -> any any (msg:"NPM Supply Chain: TLS SNI Connection to Axios RAT C2 (sfrclak.com)"; \
    tls.sni; content:"sfrclak.com"; nocase; \
    reference:url,socradar.io/blog/axios-npm-supply-chain-attack-2026-ciso-guide/; \
    classtype:trojan-activity; sid:9000103; rev:1;)

# 4. Erkennung des Downloads des schädlichen Pakets 'plain-crypto-js' über HTTP
# (Hinweis: greift nur, falls kein HTTPS genutzt wird oder ein TLS-Proxy/SSL-Inspection aktiv ist)
alert http $HOME_NET any -> any any (msg:"NPM Supply Chain: Attempt to download malicious dependency (plain-crypto-js)"; \
    http.uri; content:"/plain-crypto-js/-/plain-crypto-js-4.2.1.tgz"; fast_pattern; \
    reference:url,socradar.io/blog/axios-npm-supply-chain-attack-2026-ciso-guide/; \
    classtype:attempted-user; sid:9000104; rev:1;)

# 5. Erkennung des Downloads der kompromittierten Axios-Version 1.14.1
alert http $HOME_NET any -> any any (msg:"NPM Supply Chain: Attempt to download compromised Axios version (1.14.1)"; \
    http.uri; content:"/axios/-/axios-1.14.1.tgz"; fast_pattern; \
    reference:url,socradar.io/blog/axios-npm-supply-chain-attack-2026-ciso-guide/; \
    classtype:attempted-user; sid:9000105; rev:1;)

SIEM

Wazuh kann mittels der wazuh-agents bei diesem speziellen Hash ebenfalls einen Alarm auslösen (z.B. Level 12 oder höher). Dabei muss man jedoch selbst etwas mithelfen. Die Axios-Malware installiert die Datei setup.js, führt sie aus und löscht sie danach sofort wieder, um Spuren zu verwischen. Ein periodischer FIM-Scan (z. B. alle 12 Stunden) würde diese Datei aufgrund der kurzen Lebenserwartung übersehen.

Ich habe meiner /var/ossec/etc/rules/local_rules.xml daher einfach folgendes hinzugefügt:

<group name="syscheck,supply_chain_attack,">
  <!-- WAVESHAPER.V2 Linux Python RAT -->
  <rule id="100010" level="14">
    <if_sid>554</if_sid>
    <field name="syscheck.sha256_after">fcb81618bb15edfdedfb638b4c08a2af9cac9ecfa551af135a8402bf980375cf</field>
    <description>CRITICAL: WAVESHAPER.V2 Linux Python RAT detected!</description>
    <mitre>
      <id>T1195.002</id>
    </mitre>
  </rule>

  <!-- WAVESHAPER.V2 macOS Native Binary -->
  <rule id="100011" level="14">
    <if_sid>554</if_sid>
    <field name="syscheck.sha256_after">92ff08773995ebc8d55ec4b8e1a225d0d1e51efa4ef88b8849d0071230c9645a</field>
    <description>CRITICAL: WAVESHAPER.V2 macOS Native Binary detected!</description>
    <mitre>
      <id>T1195.002</id>
    </mitre>
  </rule>

  <!-- WAVESHAPER.V2 Windows Stage 1 -->
  <rule id="100012" level="14">
    <if_sid>554</if_sid>
    <field name="syscheck.sha256_after">617b67a8e1210e4fc87c92d1d1da45a2f311c08d26e89b12307cf583c900d101</field>
    <description>CRITICAL: WAVESHAPER.V2 Windows Stage 1 detected!</description>
    <mitre>
      <id>T1195.002</id>
    </mitre>
  </rule>

  <!-- WAVESHAPER.V2 Additional Hash -->
  <rule id="100013" level="14">
    <if_sid>554</if_sid>
    <field name="syscheck.sha256_after">ed8560c1ac7ceb6983ba995124d5917dc1a00288912387a6389296637d5f815c</field>
    <description>CRITICAL: WAVESHAPER.V2 Malware Hash detected!</description>
    <mitre>
      <id>T1195.002</id>
    </mitre>
  </rule>

  <!-- SILKBELL / Axios NPM Supply Chain (setup.js) -->
  <rule id="100014" level="14">
    <if_sid>554</if_sid>
    <field name="syscheck.sha256_after">e10b1fa84f1d6481625f741b69892780140d4e0e7769e7491e5f4d894c2e0e09</field>
    <description>CRITICAL: SILKBELL/Axios NPM Supply Chain Malware (setup.js) detected!</description>
    <mitre>
      <id>T1195.002</id>
    </mitre>
  </rule>

  <!-- system.bat -->
  <rule id="100015" level="14">
    <if_sid>554</if_sid>
    <field name="syscheck.sha256_after">f7d335205b8d7b20208fb3ef93ee6dc817905dc3ae0c10a0b164f4e7d07121cd</field>
    <description>CRITICAL: Malicious system.bat detected!</description>
    <mitre>
      <id>T1195.002</id>
    </mitre>
  </rule>

  <!-- plain-crypto-js-4.2.1.tgz -->
  <rule id="100016" level="14">
    <if_sid>554</if_sid>
    <field name="syscheck.sha256_after">58401c195fe0a6204b42f5f90995ece5fab74ce7c69c67a24c61a057325af668</field>
    <description>CRITICAL: Malicious NPM package plain-crypto-js-4.2.1.tgz detected!</description>
    <mitre>
      <id>T1195.002</id>
    </mitre>
  </rule>
</group>

Zusätzlich habe ich meinem Update-Script, das per cronjob aufgerufen wird, diesen Hash ebenfalls mitgegeben. Warum auch nicht:

#!/bin/bash
# /var/ossec/bin/update_malicious_ips.sh
# ---------------------------------------------------------
# Wazuh Threat Intel Updater
# Aktualisiert IPs und Domains für CDB-Listen
# ---------------------------------------------------------

unalias rm > /dev/null 2>&1
unalias mv > /dev/null 2>&1

# Pfade
LIST_PATH="/var/ossec/etc/lists/malicious-ioc"
IP_FILE="$LIST_PATH/malicious-ip"
DOMAIN_FILE="$LIST_PATH/malicious-domains"
HASH_FILE="$LIST_PATH/malware-hashes"

# Temp Dateien
TEMP_IP="/tmp/malicious_ips.txt"
TEMP_DOMAIN="/tmp/malicious_domains.txt"

# User/Group
WAZUH_USER="wazuh"
WAZUH_GROUP="wazuh"

echo "Starte Update Prozess..."

# ---------------------------------------------------------
# 1. IP-Liste Update (GreenSnow)
# ---------------------------------------------------------
echo "[IP] Lade GreenSnow Liste herunter..."
# -L folgt Redirects, --connect-timeout verhindert langes Hängen
if curl -s -L --connect-timeout 10 "https://blocklist.greensnow.co/greensnow.txt" -o $TEMP_IP; then
    if [ -s $TEMP_IP ]; then
        sed -i 's/$/:malicious/' $TEMP_IP
        mv $TEMP_IP $IP_FILE
        echo "[IP] OK."
    else
        echo "[IP] Datei leer. Überspringe."
    fi
else
    echo "[IP] Download fehlgeschlagen."
fi

# ---------------------------------------------------------
# 2. Domain-Liste Update (Quelle: DigitalSide via GitHub)
# ---------------------------------------------------------
# HINWEIS: Die originale URL osint.digitalside.it ist oft offline.
# Wir nutzen den offiziellen GitHub Mirror (Raw content).
DOMAIN_URL="https://raw.githubusercontent.com/davidonzo/Threat-Intel/master/lists/latestdomains.txt"

echo "[DOMAIN] Lade Domain Liste (GitHub Mirror)..."
if curl -s -L --connect-timeout 10 "$DOMAIN_URL" -o $TEMP_DOMAIN; then
    if [ -s $TEMP_DOMAIN ]; then
        # Bereinigen: Kommentare entfernen
        sed -i '/^#/d' $TEMP_DOMAIN
        # Leere Zeilen entfernen
        sed -i '/^$/d' $TEMP_DOMAIN
        # Formatieren: Anfügen von ":malicious"
        sed -i 's/$/:malicious/' $TEMP_DOMAIN
        
        # Verschieben
        mv $TEMP_DOMAIN $DOMAIN_FILE
        echo "[DOMAIN] OK."
    else
        echo "[DOMAIN] Datei leer. Überspringe."
    fi
else
    echo "[DOMAIN] Download fehlgeschlagen. Prüfe Internetverbindung oder URL."
fi

# ---------------------------------------------------------
# 3. Hash-Liste Check
# ---------------------------------------------------------
if [ ! -s $HASH_FILE ]; then
    echo "[HASH] Erstelle Hashes."
cat > $HASH_FILE << 'EOF'
fcb81618bb15edfdedfb638b4c08a2af9cac9ecfa551af135a8402bf980375cf:malicious
92ff08773995ebc8d55ec4b8e1a225d0d1e51efa4ef88b8849d0071230c9645a:malicious
617b67a8e1210e4fc87c92d1d1da45a2f311c08d26e89b12307cf583c900d101:malicious
ed8560c1ac7ceb6983ba995124d5917dc1a00288912387a6389296637d5f815c:malicious
e10b1fa84f1d6481625f741b69892780140d4e0e7769e7491e5f4d894c2e0e09:malicious
f7d335205b8d7b20208fb3ef93ee6dc817905dc3ae0c10a0b164f4e7d07121cd:malicious
58401c195fe0a6204b42f5f90995ece5fab74ce7c69c67a24c61a057325af668:malicious
EOF
fi

# ---------------------------------------------------------
# 4. Berechtigungen und Reload
# ---------------------------------------------------------
chown $WAZUH_USER:$WAZUH_GROUP $IP_FILE $DOMAIN_FILE $HASH_FILE
chmod 660 $IP_FILE $DOMAIN_FILE $HASH_FILE

echo "Lade Wazuh Manager neu..."
if command -v systemctl &> /dev/null; then
    systemctl reload wazuh-manager
else
    /var/ossec/bin/wazuh-control reload
fi

echo "Fertig."

Auf diese Weise wird meine lokale KI sofort aktiviert, um den Incident zu untersuchen.

Forensische Analyse mit dem Diagnose Skript

Da das Dateisystem im Nachhinein bereinigt wird, müssen andere Indikatoren zur Erkennung herangezogen werden. Hierbei spielen Lockfiles (package-lock.json, yarn.lock) eine zentrale Rolle, da sie historisch und unveränderlich aufzeichnen, welche Versionen zu welchem Zeitpunkt gezogen wurden. Zusätzlich finden sich häufig Überreste des manipulierten Tarballs im globalen npm-Cache oder Netzwerkverbindungen in den Systemprotokollen.

Um diesen Vorgang zu automatisieren, habe ich das folgende forensische Bash-Skript für Debian-basierte Systeme geschrieben. Es durchsucht die genannten Pfade nach den exakten Indikatoren (Hashes, IPs und Paketversionen). Für eine lückenlose Analyse der Systemprotokolle unter /var/log muss das Skript mit Root-Rechten ausgeführt werden. So erhält man ersteinmal ein schnelles, vorläufiges Ergebnis.

#!/bin/bash
# IOC Scanner: Axios NPM Supply Chain Attack (03/2026) | M. Meister

RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
BLUE='\033[0;34m'
NC='\033[0m'

echo -e "${BLUE}====================================================${NC}"
echo -e "${BLUE}  Axios RAT Supply Chain Scanner (März 2026)        ${NC}"
echo -e "${BLUE}====================================================${NC}"

# Startverzeichnis definieren (Standard: /var/www)
SEARCH_DIR="${1:-/var/www}"
[ ! -d "$SEARCH_DIR" ] && SEARCH_DIR="/"

FOUND_IOCS=0

# Definition der Indicators of Compromise
MALICIOUS_PKGS=("axios@1.14.1" "axios@0.30.4" "plain-crypto-js@4.2.1")
C2_SERVERS=("sfrclak.com" "142.11.206.73")
MALICIOUS_SHA256="e10b1fa84f1d6481625f741b69892780140d4e0e7769e7491e5f4d894c2e0e09"

echo -e "${YELLOW}Starte forensischen Scan im Verzeichnis: ${SEARCH_DIR}${NC}\n"

# 1. Lockfiles überprüfen (Die absolute Quelle der Wahrheit)
echo -e "${YELLOW}[1/4] Durchsuche Lockfiles nach kompromittierten Abhängigkeiten...${NC}"
while read -r lockfile; do
    for pkg in "${MALICIOUS_PKGS[@]}"; do
        if grep -q "$pkg" "$lockfile"; then
            echo -e "${RED}[!] ALARM: Schädliche Paketversion '$pkg' gefunden in: $lockfile${NC}"
            ((FOUND_IOCS++))
        fi
    done
# Ignoriere node_modules, da hier Anti-Forensik betrieben wurde
done < <(find "$SEARCH_DIR" -type f \( -name "package-lock.json" -o -name "yarn.lock" -o -name "pnpm-lock.yaml" \) -not -path "*/node_modules/*" 2>/dev/null)

# 2. Globalen NPM Cache prüfen
echo -e "\n${YELLOW}[2/4] Prüfe globalen NPM-Cache auf 'plain-crypto-js'...${NC}"
if command -v npm >/dev/null 2>&1; then
    NPM_CACHE=$(npm config get cache 2>/dev/null)
    if [ -n "$NPM_CACHE" ] && [ -d "$NPM_CACHE" ]; then
        if find "$NPM_CACHE" -type f -path "*plain-crypto-js*" 2>/dev/null | grep -q ".*"; then
            echo -e "${RED}[!] ALARM: Spuren von 'plain-crypto-js' im NPM-Cache gefunden ($NPM_CACHE).${NC}"
            ((FOUND_IOCS++))
        fi
    fi
else
    echo "NPM ist nicht installiert. Überspringe Cache-Check."
fi

# 3. Datei-Hashes abgleichen (Falls das Bereinigungsskript fehlschlug)
echo -e "\n${YELLOW}[3/4] Suche im Dateisystem nach Malware-Hashes...${NC}"
while read -r jsfile; do
    if [ "$(sha256sum "$jsfile" | awk '{print $1}')" == "$MALICIOUS_SHA256" ]; then
        echo -e "${RED}[!] ALARM: Kompromittierte Datei (Hash-Match) gefunden: $jsfile${NC}"
        ((FOUND_IOCS++))
    fi
done < <(find "$SEARCH_DIR" -type f -name "setup.js" 2>/dev/null)

# 4. Logs auf C2-Netzwerkverkehr prüfen
echo -e "\n${YELLOW}[4/4] Prüfe System-Logs auf C2-Verbindungen...${NC}"
if [ -d "/var/log" ]; then
    for c2 in "${C2_SERVERS[@]}"; do
        MATCHES=$(grep -rnl "$c2" /var/log --exclude="*.gz" 2>/dev/null)
        if [ -n "$MATCHES" ]; then
            echo -e "${RED}[!] ALARM: C2-Traffic zu '$c2' in Protokollen gefunden:${NC}\n$MATCHES"
            ((FOUND_IOCS++))
        fi
    done
else
    echo "Konnte /var/log nicht lesen. Fehlen die Root-Rechte?"
fi

# Zusammenfassung
echo -e "\n${BLUE}====================================================${NC}"
if [ "$FOUND_IOCS" -gt 0 ]; then
    echo -e "${RED}ERGEBNIS: SYSTEM WAHRSCHEINLICH KOMPROMITTIERT ($FOUND_IOCS IOCs gefunden)${NC}"
else
    echo -e "${GREEN}ERGEBNIS: Keine aktiven Indikatoren gefunden.${NC}"
fi
echo -e "${BLUE}====================================================${NC}"

Im besten Fall sieht das Ergebniss dann so aus:

Incident Response nach einem positiven Befund

Schlägt das Skript an, ist sofortiges Handeln erforderlich. Es wird eindringlich davor gewarnt, die Malware im laufenden Betrieb einfach löschen zu wollen. Ein kompromittierter Host ist kein leicht verschmutztes Auto, das sich mit einem feuchten Lappen reinigen lässt, sondern ein sicherheitstechnischer Totalschaden. Die Systeme müssen umgehend vom Netzwerk isoliert werden.

Da der RAT darauf ausgelegt ist, sensible Daten auszulesen, muss pauschal davon ausgegangen werden, dass sämtliche Git-Deploy-Keys, Cloud-IAM-Rollen, .env-Dateien und Passwörter kompromittiert wurden. Diese Geheimnisse müssen global rotiert werden, wie es auch bei regulärer Vorfallbehandlung im Security Operations Center (SOC) Best Practice ist. Das System selbst darf ausschließlich aus einem verifizierten Backup wiederhergestellt werden, das vor dem 30. März 2026 erstellt wurde.

Fazit

Der Axios-Vorfall vom März 2026 demonstriert eindrucksvoll, dass selbst millionenfach vertraute Open-Source-Komponenten über Nacht zur kritischen Gefahr für die eigene Infrastruktur werden können. Durch die fortgeschrittenen Anti-Forensik-Funktionen der Malware lässt sich eine Kompromittierung oft nur noch über historische Lockfiles und Netzwerkprotokolle nachweisen. Letztlich bleiben strenge CI/CD-Sicherheitsrichtlinien, das konsequente Pinning von Abhängigkeiten und eine saubere Backup-Strategie die einzig verlässlichen Schutzschilde gegen derartige Lieferketten-Angriffe.