A ferramenta de gateway para modelos de linguagem LiteLLM sofreu um envenenamento da cadeia de suprimentos em 21 de outubro. A empresa de segurança em nuvem Wiz divulgou que a versão adulterada LiteLLM 1.107.0 foi publicada no PyPI no mesmo dia, e que as imagens no GHCR e no Docker Hub com as tags v1.107.0, latest, main-latest e main-stable também receberam o mesmo programa de roubo de dados. A versão segura mais recente indicada oficialmente é a v1.106.2.
O LiteLLM é desenvolvido pela BerriAI e costuma ser usado como uma camada de proxy dentro da empresa, encaminhando, por uma interface unificada, requisições para centenas de serviços de modelos, como OpenAI, Anthropic e Bedrock. Por trás do proxy ficam armazenadas as chaves de API de cada fornecedor, e foi exatamente esse o alvo do ataque.
Instalou, começou a roubar
O pacote malicioso coloca três arquivos na raiz de site-packages: cook.pth, cook.py e sitecustomize.py. Os dois primeiros exploram o mecanismo .pth do Python e são executados assim que o interpretador inicia, sem que nenhum código da aplicação precise importar o LiteLLM.
O programa de roubo chama-se internamente privcollect, tem 16 módulos e mira os seguintes alvos:
- Credenciais e cookies de navegador do Chrome, Firefox, Edge e Safari
- Credenciais de nuvem da AWS, GCP e Azure
- Chaves de API de empresas de IA como OpenAI, Anthropic e Cohere
- Chaves privadas SSH e GPG e o histórico do shell
- Credenciais de fornecedores upstream consultadas diretamente no banco de dados PostgreSQL do LiteLLM Proxy
Os dados são primeiro cifrados com AES-256-CBC, a chave é protegida por uma camada de RSA-4096 e tudo é enviado por HTTP POST ao domínio falso registrado pelos atacantes, www.litellm[.]dev. O sitecustomize.py só roda em Linux e macOS e busca o endereço da segunda etapa em um repositório do tipo "caixa postal morta" no GitHub; a Wiz afirma que esse arquivo nunca teve conteúdo além de valores de teste, e o GitHub já removeu o repositório.
A linha do tempo, em detalhe
Com base nos horários UTC divulgados pela Wiz, dá para estimar cada janela de forma aproximada:
| Etapa | Horário (UTC) | Duração |
|---|---|---|
| Repositório falso recebe 10 commits | 08:56–10:46 | cerca de 1 h 50 min |
| Versão maliciosa no ar no PyPI | 11:39–13:20 | cerca de 1 h 41 min |
| Tags do Docker adulteradas no ar | retiradas por volta das 13:53 | cerca de 2 h 14 min contados da publicação no PyPI |
| Atacantes validam credenciais da AWS | 16:20–17:01 | cerca de 4,5 h após a exfiltração |
Pouco mais de uma hora no PyPI parece pouco, mas tags como latest são puxadas automaticamente por inúmeros pipelines de CI e implantações em Kubernetes, de modo que a exposição depende sobretudo de quantos ambientes reconstruíram imagens nesse intervalo. A Wiz não informou o número de downloads, e a quantidade de organizações afetadas também não pode ser verificada por ora.
Com as credenciais em mãos, os atacantes usaram as funções de instância da AWS dos runners de CI e dos nós Kubernetes comprometidos para chamar interfaces como sts:GetCallerIdentity e bedrock:ListFoundationModels. A Wiz considera o comportamento compatível com LLMjacking, ou seja, o uso indevido de contas de nuvem alheias para consumir modelos de linguagem de graça; em alguns ambientes, os atacantes ainda enumeraram o IAM em um reconhecimento de rotina.
Suspeita-se que a porta de entrada foi um token do GitHub
Os 10 commits enviados pelos atacantes foram parar no repositório falso Berri-AI/litellm; os nove primeiros tinham assinatura do GitHub, e o último não era assinado e usava outro e-mail. A BerriAI declarou:
"malicious actions were taken through three engineers' GitHub accounts"
(As ações maliciosas foram realizadas por meio das contas do GitHub de três engenheiros.)
O LiteLLM suspeita que esses tokens OAuth do GitHub CLI tenham vazado de uma instalação interna exposta à internet, possivelmente ligada a uma vulnerabilidade corrigida havia pouco; a Wiz deixa claro que isso ainda não foi confirmado. A BerriAI afirma que todos os tokens envolvidos foram revogados. Equipes que usaram a 1.107.0 ou puxaram as imagens citadas nesse período precisam rotacionar todas as credenciais de nuvem, chaves de modelos e chaves privadas SSH acessíveis nas máquinas.
Fontes: CocoLoop, blog de pesquisa da Wiz, comunicado do Wiz Threat Intelligence Center, declaração pública da BerriAI; foram conferidos as versões e tags de imagem afetadas, os nomes dos arquivos maliciosos e os horários UTC de cada etapa.