Una versión del paquete de Python LiteLLM publicada en PyPI el 21 de octubre incluía un robador de credenciales y una puerta trasera de acceso remoto. Al instalar la versión 1.107.0 se colocaron tres archivos en la carpeta site-packages. Dos de ellos se ejecutaban cada vez que iniciaba cualquier proceso de Python en el equipo, incluidos los procesos que nunca tocaban LiteLLM. PyPI ya eliminó la versión.

SafeDep, la firma de seguridad que analizó el paquete, dijo que el código fuente original en GitHub no contiene los archivos maliciosos. Las versiones 1.106.2, 1.107.0rc1 y 1.107.0rc2 están limpias, al igual que los paquetes complementarios de los que depende la 1.107.0.

¿Qué robó la versión maliciosa 1.107.0 de LiteLLM?

El primer archivo, cook.pth, le indica a Python que importe un segundo archivo, cook.py. Ese archivo es un robador de credenciales. Según SafeDep, recopila llaves SSH, credenciales de la nube, secretos de CI/CD, tokens de herramientas de IA, contraseñas de navegadores y las llaves de proveedores de LLM almacenadas en la base de datos del proxy de LiteLLM. Luego cifra lo robado y lo sube a www.litellm[.]dev.

El tercer archivo, sitecustomize.py, inicia un proceso en segundo plano que se activa cada hora. Lee una dirección de servidor desde un archivo en un repositorio de GitHub, vuelve a ejecutar el robador y luego descarga y ejecuta el código que devuelva ese servidor. La cuenta y el repositorio de GitHub fueron eliminados unas dos horas después de publicarse la versión y, en el momento en que SafeDep lo revisó, la puerta trasera no tenía una dirección de servidor a la cual conectarse. Los equipos que ejecutaron el proceso antes de la eliminación pudieron haber recibido y ejecutado código de segunda etapa. SafeDep dijo que no pudo recuperar la dirección del servidor.

Cómo llegó el código malicioso a la versión publicada

¿Cómo llegó el código malicioso a la versión publicada en PyPI?

El problema empezó en la distribución de código fuente, el archivo del paquete a partir del cual pip puede construir la instalación. Su archivo pyproject.toml contiene una línea que no aparece en el repositorio público: una configuración de datos que copia una carpeta llamada cook dentro del wheel. El archivo de código fuente deja fuera esa carpeta, así que la línea adicional es la única señal visible del cambio.

La versión tampoco coincidía con su propia etiqueta. La etiqueta v1.107.0 apunta a una confirmación que indica la versión 1.108.0 en su archivo de proyecto. SafeDep encontró que el archivo coincidía con una confirmación posterior en la rama principal, con cinco archivos editados y la carpeta agregada. Las ediciones volvieron a poner la versión en 1.107.0 y fijaron los paquetes complementarios a los valores usados en la candidata de versión anterior, lo que evitó que una comparación de dependencias contra rc2 mostrara algo inusual.

Los wheels maliciosos fueron construidos para parecer resultados normales del proceso de publicación del proyecto. Muestran la misma versión de la herramienta de compilación que las versiones legítimas, y sus registros de archivo no presentan cambios después de la compilación. Ninguna ejecución pública de GitHub Actions compiló o publicó la versión. SafeDep revisó 539 ejecuciones entre las 09:30 y las 12:30 UTC y no encontró ninguna que la hubiera producido. La versión en GitHub se creó unos 10 minutos después de la subida a PyPI, mediante una cuenta de bot, y el mismo retraso ocurrió con la versión 1.106.2. PyPI no tiene atestaciones de procedencia para las versiones 1.107.0, 1.106.2 ni rc2.

SafeDep afirmó, con confianza moderada a alta, que la canalización privada de publicación del proyecto compiló los wheels a partir de un código fuente modificado por el atacante. Dijo que una credencial comprometida de un mantenedor o de un bot, una rama privada o un espejo, o la referencia desde la que la canalización compila podrían explicar las evidencias. Un token robado de PyPI usado desde las máquinas del atacante encaja menos. Solo los registros de la canalización del proyecto pueden confirmar cómo ocurrió.

Qué busca el robador

El robador se ejecuta en cada proceso de Python de un equipo infectado, incluidos aplicaciones, pip, servidores de lenguaje de los IDE y trabajos de CI. Está organizado en módulos. Uno lee las contraseñas guardadas y el historial de navegación de Chromium y Firefox. Otros apuntan a llaves en ~/.ssh, historial de la terminal, credenciales de AWS, Azure, Google Cloud y Kubernetes, secretos de GitLab runner y Jenkins, y credenciales de Terraform. Otro módulo busca tokens y archivos de configuración de herramientas de programación con IA, entre ellas Claude Code, Cursor, Windsurf, Copilot y Gemini CLI, además de tokens de Hugging Face.

El módulo de bases de datos es especialmente sensible para los equipos que ejecutan LiteLLM como proxy. Lee la cadena de conexión a la base de datos y extrae las tablas que contienen las llaves API de los proveedores de LLM. El robador también consulta el servicio de metadatos de instancias de AWS para obtener la identidad de la instancia y las credenciales de sus roles, y lee variables de entorno de otros procesos en ejecución.

¿Qué deben hacer los usuarios que instalaron litellm 1.107.0?

Quienes hayan instalado litellm 1.107.0 deben asumir que las credenciales de esos equipos pudieron haber sido robadas. SafeDep enumera los indicadores de compromiso, entre ellos el dominio de subida, los nombres de los archivos plantados y sus hashes, y un archivo marcador en /tmp que muestra que el robador ya se ejecutó en un equipo. Los usuarios que tengan los tres archivos en site-packages deben eliminarlos y rotar todas las credenciales a las que el equipo pudo acceder.

Cet article a été rédigé avec l'assistance de l'IA.
News Factory APP - actualités agentiques pour booster votre SEO et AEO.