SOC Prime Bias: Critique

08 Jun 2026 19:43 UTC

Du préinstallation à la persistance : À l’intérieur de la campagne de vol d’identifiants Red Hat npm Miasma

Author Photo
SOC Prime Team linkedin icon Suivre
Du préinstallation à la persistance : À l’intérieur de la campagne de vol d’identifiants Red Hat npm Miasma
shield icon

Detection stack

  • AIDR
  • Alert
  • ETL
  • Query

Résumé

Microsoft Defender a identifié une compromission de la chaîne d’approvisionnement affectant 32 packages npm publiés sous le @redhat-cloud-services namespace. Les attaquants ont intégré un crochet de pré-installation qui déploie un chargeur JavaScript fortement obfusqué, qui récupère ensuite l’environnement d’exécution Bun et un voleur d’informations d’identification de deuxième étape. Le malware récolte des jetons de GitHub, npm, principaux fournisseurs de cloud, HashiCorp Vault, et Kubernetes, puis republie les packages empoisonnés pour continuer à se propager. La campagne inclut également une sauvegarde destructrice qui efface le répertoire personnel de la victime si un jeton leurre est détecté.

Enquête

L’enquête a retracé la violation initiale à un pipeline CI/CD compromis pour RedHatInsights/javascript-clients, où les attaquants ont abusé d’un workflow OIDC GitHub Actions légitime pour publier des packages trojanisés avec des signatures de provenance valides. L’analyse du dropper a révélé plusieurs couches d’obfuscation, incluant un encodage basé sur ROT, un chiffrement AES-128-GCM, et un chiffre personnalisé, avant que Bun ne soit exécuté pour lancer la charge utile de deuxième étape. Les acteurs de la menace ont également extrait la mémoire des courtiers GitHub Actions pour extraire directement les secrets des processus actifs.

Atténuation

Microsoft recommande de revoir les arbres de dépendance pour les @redhat-cloud-services packages affectés, de figer les versions de confiance et de désactiver l’exécution des scripts npm avec le --ignore-scripts flag lorsque cela est possible. Tous les jetons npm compromis doivent être révoqués et réémis, et les comptes GitHub doivent être examinés pour les créations de dépôts non autorisées ou les activités suspectes. Des mesures de sauvegarde supplémentaires ont été mises en œuvre dans le @redhat-cloud-services namespace pour empêcher les publications non autorisées.

Réponse

Les défenseurs devraient détecter l’exécution suspecte de pré-installation npm et les lancements inattendus de l’environnement d’exécution Bun à partir de répertoires temporaires. La surveillance devrait également couvrir la création de dépôts GitHub publics inconnus et les schémas d’utilisation inhabituels des jetons. Les défenses réseau devraient bloquer ou alerter sur les connexions aux URL de téléchargement Bun connues et au domaine api.anthropic.com . Toutes les informations d’identification potentiellement exposées doivent être immédiatement tournées, et la mémoire des courtiers CI/CD doit être examinée pour détecter les signes de fuites de secrets.

"graph TB %% Class Definitions classDef action fill:#99ccff classDef tool fill:#cccccc classDef malware fill:#ffcc99 classDef process fill:#ff9966 %% Nodes node_sc_001["<b>Action</b> – <b>T1195.001 Compromission de la Chaîne d’Approvisionnement</b> : Compromission des Dépendances Logiciels et Outils de Développement<br/>L’attaquant a détourné le pipeline CI/CD RedHatInsights/javascript-clients et utilisé GitHub Actions OIDC pour publier des packages npm trojanisés @redhat-cloud-services."] class node_sc_001 action tool_github_oidc["<b>Outil</b> – <b>Nom</b> : GitHub Actions OIDC<br/><b>Description</b> : Intégration OpenID Connect fournissant des jetons à courte vie pour les workflows CI."] class tool_github_oidc tool malicious_preinstall["<b>Malware</b> – <b>T1127.003 Exécution de Proxy pour Utilitaires de Développeur de Confiance</b> : Crochet de pré-installation malveillant dans package.json exécuté automatiquement pendant <code>npm install</code>, lançant <code>node index.js</code>."] class malicious_preinstall malware installer_trigger["<b>Action</b> – <b>T1546.016 Exécution Déclenchée par Événement</b> : Déclencheur de package d’installation qui lance le dropper lorsque le script de pré-installation est invoqué."] class installer_trigger action obfuscated_payload["<b>Malware</b> – <b>T1027.009 Fichiers ou Informations Obfusqués</b> : Charge utile incorporée (index.js de 4,29 Mo) utilisant ROT multicouche, AES‑128‑GCM, chaîne-tableau et chiffre PBKDF2 personnalisé pour cacher son code."] class obfuscated_payload malware dynamic_resolution["<b>Malware</b> – <b>T1027.007 Fichiers ou Informations Obfusqués</b> : Résolution d’API Dynamique – la déobfuscation à l’exécution résout les URL pour l’environnement Bun et les points finaux C2."] class dynamic_resolution malware ingress_transfer["<b>Action</b> – <b>T1105 Transfert d’Outil d’Entrée</b> : Le dropper télécharge l’environnement d’exécution JavaScript Bun à partir des URL de diffusion officielles avant d’exécuter la charge utile de deuxième étape."] class ingress_transfer action tool_bun_runtime["<b>Outil</b> – <b>Nom</b> : Environnement d’Exécution JavaScript Bun<br/><b>Description</b> : Moteur JavaScript haute performance utilisé comme environnement d’exécution pour la deuxième étape."] class tool_bun_runtime tool metadata_query["<b>Action</b> – <b>T1552.005 Informations d’Identification Non Sécurisées</b> : API de Métadonnées d’Instance Cloud<br/>Interroge les services de métadonnées AWS/ECS, Azure IMDS et GCP pour obtenir des jetons d’accès cloud."] class metadata_query action file_credential["<b>Action</b> – <b>T1552.001 Informations d’Identification Non Sécurisées</b> : Informations d’Identification dans les Fichiers<br/>Extrait les fichiers locaux pour les clés SSH, les configurations CLI, les fichiers de portefeuilles de cryptomonnaie et autres matériaux secrets."] class file_credential action token_harvest["<b>Action</b> – <b>T1528 Voler un Jeton de l’Application</b> : Récolte les jetons des courtiers GitHub Actions, jetons npm OIDC et autres jetons de fournisseur."] class token_harvest action browser_discovery["<b>Action</b> – <b>T1217 Découverte d’Informations du Navigateur</b> : Collecte les magasins du navigateur et les fichiers de portefeuille de cryptomonnaie à partir des postes de travail des développeurs."] class browser_discovery action elevation_control["<b>Action</b> – <b>T1548 Abuser du Mécanisme de Contrôle d’Élévation</b> : Installe une règle sudo sans mot de passe via un montage bind de <code>/etc/sudoers.d</code> pour obtenir des privilèges root."] class elevation_control action exfiltration_git["<b>Action</b> – <b>T1048 Exfiltration via un Protocole Alternatif</b> : Exfiltre les informations d’identification volées en créant des dépôts GitHub sous le compte de la victime, en commettant des fichiers JSON, et utilise également un point final HTTPS alternatif."] class exfiltration_git action destructive_cleanup["<b>Action</b> – <b>T1070.010 Suppression d’Indicateur</b> : Repositionne le malware et, si un jeton leurre est utilisé, exécute <code>rm -rf ~/</code> pour effacer le répertoire personnel de l’utilisateur."] class destructive_cleanup action node_sc_002["<b>Action</b> – <b>T1195.002 Compromission de la Chaîne d’Approvisionnement</b> : Compromission de la Chaîne d’Approvisionnement Logiciel – packages empoisonnés republiés avec une provenance SLSA falsifiée, permettant une propagation de type ver vers les projets en aval."] class node_sc_002 action %% Connections node_sc_001 –>|utilise| tool_github_oidc tool_github_oidc –>|exécute| malicious_preinstall malicious_preinstall –>|déclenche| installer_trigger installer_trigger –>|exécute| obfuscated_payload obfuscated_payload –>|effectue| dynamic_resolution dynamic_resolution –>|télécharge| ingress_transfer ingress_transfer –>|installe| tool_bun_runtime tool_bun_runtime –>|interroge| metadata_query metadata_query –>|extrait| file_credential file_credential –>|récolte| token_harvest token_harvest –>|collecte| browser_discovery browser_discovery –>|active| elevation_control elevation_control –>|exfiltre via| exfiltration_git exfiltration_git –>|peut déclencher| destructive_cleanup destructive_cleanup –>|facilite| node_sc_002 node_sc_002 –>|se propage à| node_sc_001 "

Flux d’Attaque

Exécution de Simulation

Prérequis : La vérification pré-vol de la Télémétrie et du Baseline doit avoir réussi.

Justification : Cette section détaille l’exécution précise de la technique de l’adversaire (TTP) conçue pour déclencher la règle de détection. Les commandes et le récit DOIVENT refléter directement les TTPs identifiés et viser à générer exactement la télémétrie attendue par la logique de détection.

  • Récit et Commandes de l’Attaque :
    Un adversaire ayant déjà compromis une VM GCE utilise une approche vivre-sur-terrain pour récolter le jeton du compte de service par défaut de la VM. Les étapes sont :

    1. Sondez le serveur de métadonnées pour vérifier qu’il est accessible.
    2. Émettre une demande de jeton to http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token avec l’en-tête requis Metadata-Flavor : Google .
    3. Enregistrez le JSON retourné (contient access_token, expires_in, token_type).
    4. Utilisez le jeton pour appeler une API GCP privilégiée (p.ex., lister tous les buckets) pour démontrer des informations d’identification exploitables.

    Cette séquence exacte génère l’événement d’audit GCPServiceAccountTokenAccess, qui correspond à la règle Sigma sélection.

  • Script de Test de Régression :

    #!/usr/bin/env bash
    set -euo pipefail
    
    # 1. Vérifiez la réactivité du serveur de métadonnées
    echo "[*] Sondage du serveur de métadonnées..."
    curl -s -H "Metadata-Flavor: Google" 
     "http://metadata.google.internal/computeMetadata/v1/instance/id" >/dev/null
    
    # 2. Récoltez le jeton du compte de service par défaut
    echo "[*] Demande de jeton de compte de service..."
    TOKEN_RESPONSE=$(curl -s -H "Metadata-Flavor: Google" 
     "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token")
    
    echo "[+] Réponse de jeton reçue :"
    echo "${TOKEN_RESPONSE}" | jq .
    
    # 3. Extrayez le jeton d'accès
    ACCESS_TOKEN=$(echo "${TOKEN_RESPONSE}" | jq -r '.access_token')
    
    # 4. Utilisez le jeton pour lister les buckets GCS (démontre l'utilité du jeton)
    echo "[*] Utilisation du jeton pour lister les buckets GCS..."
    curl -s -H "Authorization: Bearer ${ACCESS_TOKEN}" 
     "https://storage.googleapis.com/storage/v1/b" | jq .
    
    echo "[+] Simulation terminée. Les actions ci-dessus devraient avoir produit un événement d'audit GCPServiceAccountTokenAccess."
  • Commandes de Nettoyage :

    # Aucun changement persistant n'a été effectué ; seulement suppression des variables temporaires.
    unset TOKEN_RESPONSE ACCESS_TOKEN
    echo "[*] Nettoyage terminé."