LiteLLM 1.107.0, envenenado para robar claves de IA

La herramienta de pasarela para modelos de lenguaje LiteLLM sufrió el 21 de octubre un ataque de envenenamiento de su cadena de suministro. La empresa de seguridad en la nube Wiz reveló que la versión manipulada, LiteLLM 1.107.0, se publicó en PyPI ese mismo día, y que las imágenes de GHCR y Docker Hub con las etiquetas v1.107.0, latest, main-latest y main-stable también contenían el mismo programa de robo. La última versión segura que indica el proyecto es la v1.106.2.

LiteLLM lo desarrolla BerriAI y suele desplegarse como una capa de proxy interna que reenvía, mediante una interfaz unificada, las peticiones a cientos de servicios de modelos como OpenAI, Anthropic o Bedrock. Detrás del proxy se guardan las claves de API de cada proveedor, y ese fue precisamente el objetivo del ataque.

Instalar y empezar a robar

El paquete malicioso deja tres archivos en la raíz de site-packages: cook.pth, cook.py y sitecustomize.py. Los dos primeros aprovechan el mecanismo .pth de Python y se ejecutan en cuanto arranca el intérprete, sin que el código de la aplicación tenga que importar LiteLLM.

El programa de robo se llama internamente privcollect, consta de 16 módulos y apunta a lo siguiente:

  • Credenciales y cookies de los navegadores Chrome, Firefox, Edge y Safari
  • Credenciales de nube de AWS, GCP y Azure
  • Claves de API de empresas de IA como OpenAI, Anthropic y Cohere
  • Claves privadas SSH y GPG, además del historial del shell
  • Credenciales de proveedores upstream consultadas directamente en la base de datos PostgreSQL de LiteLLM Proxy

Los datos se cifran primero con AES-256-CBC, la clave se envuelve después con RSA-4096 y todo se envía mediante HTTP POST al dominio falso registrado por los atacantes, www.litellm[.]dev. El archivo sitecustomize.py solo se ejecuta en Linux y macOS y acude a un repositorio de GitHub a modo de "buzón muerto" para obtener la dirección de la segunda fase; según Wiz, salvo valores de prueba, ese archivo nunca llegó a rellenarse, y GitHub ya eliminó el repositorio.

La cronología, al detalle

A partir de las horas UTC publicadas por Wiz, se pueden calcular a grandes rasgos las distintas ventanas:

FaseHora (UTC)Duración
El repositorio falso recibe 10 commits08:56–10:46aprox. 1 h 50 min
Versión maliciosa en línea en PyPI11:39–13:20aprox. 1 h 41 min
Etiquetas de Docker manipuladas en línearetiradas hacia las 13:53aprox. 2 h 14 min desde la publicación en PyPI
Los atacantes validan credenciales de AWS16:20–17:01aprox. 4,5 h tras la exfiltración

Algo más de una hora en PyPI parece poco, pero etiquetas como latest las descargan automáticamente muchísimos pipelines de CI y despliegues de Kubernetes, así que la exposición depende sobre todo de cuántos entornos reconstruyeron imágenes en ese lapso. Wiz no ha dado cifras de descargas y, por ahora, tampoco se puede verificar cuántas organizaciones resultaron afectadas.

Con las credenciales en su poder, los atacantes utilizaron los roles de instancia de AWS de los runners de CI y los nodos de Kubernetes comprometidos para invocar interfaces como sts:GetCallerIdentity y bedrock:ListFoundationModels. Wiz considera que esto coincide con el LLMjacking, es decir, el uso de cuentas de nube ajenas para consumir modelos de lenguaje gratis; en algunos entornos, los atacantes además enumeraron IAM como parte de un reconocimiento habitual.

Se sospecha que la puerta de entrada fue un token de GitHub

Los 10 commits que enviaron los atacantes fueron a parar al repositorio falso Berri-AI/litellm; los nueve primeros llevaban firma de GitHub, mientras que el último no estaba firmado y usaba otro correo electrónico. BerriAI declaró:

"malicious actions were taken through three engineers' GitHub accounts"
(Las acciones maliciosas se realizaron a través de las cuentas de GitHub de tres ingenieros.)

LiteLLM sospecha que esos tokens OAuth de GitHub CLI se filtraron desde un despliegue interno expuesto a internet, posiblemente relacionado con una vulnerabilidad recién corregida; Wiz señala expresamente que esto aún no está confirmado. BerriAI afirma que todos los tokens implicados han sido revocados. Los equipos que usaron la 1.107.0 o descargaron en ese periodo las imágenes mencionadas deben rotar todas las credenciales de nube, claves de modelos y claves privadas SSH legibles en sus máquinas.

Fuentes: CocoLoop, blog de investigación de Wiz, aviso del Wiz Threat Intelligence Center, declaración pública de BerriAI; se contrastaron las versiones y etiquetas de imagen afectadas, los nombres de los archivos maliciosos y las horas UTC de cada fase.