Uma versão do pacote Python LiteLLM publicada no PyPI em 21 de outubro continha um roubador de credenciais e um backdoor de acesso remoto. A instalação da versão 1.107.0 colocou três arquivos na pasta site-packages. Dois deles eram executados sempre que qualquer processo Python era iniciado na máquina, inclusive processos que nunca utilizavam o LiteLLM. O PyPI já removeu a versão.
A SafeDep, empresa de segurança que analisou o pacote, afirmou que o código-fonte original no GitHub não contém os arquivos maliciosos. As versões 1.106.2, 1.107.0rc1 e 1.107.0rc2 estão limpas, assim como os pacotes complementares dos quais a 1.107.0 depende.
O que a versão maliciosa do LiteLLM 1.107.0 roubava?
O primeiro arquivo, cook.pth, instrui o Python a importar um segundo arquivo, cook.py. Esse arquivo é um roubador de credenciais. De acordo com a SafeDep, ele coleta chaves SSH, credenciais de nuvem, segredos de CI/CD, tokens de ferramentas de IA, senhas salvas em navegadores e as chaves de provedores de LLM armazenadas no banco de dados de um proxy LiteLLM. Ele criptografa os dados obtidos e os envia para www.litellm[.]dev.
O terceiro arquivo, sitecustomize.py, inicia um processo em segundo plano que é acionado a cada hora. Ele lê um endereço de servidor de um arquivo em um repositório do GitHub, executa o roubador novamente e, em seguida, baixa e executa qualquer código que esse servidor retornar. A conta e o repositório no GitHub foram excluídos cerca de duas horas após a publicação da versão e, no momento em que a SafeDep fez a verificação, o backdoor não tinha nenhum endereço de servidor para contatar. Hosts que executaram o processo antes da exclusão podem ter recebido e executado código de segundo estágio. A SafeDep afirmou não ter conseguido recuperar o endereço do servidor.
Como o código malicioso chegou à versão
Como o código malicioso entrou na versão publicada no PyPI?
O problema começou na distribuição de código-fonte, o pacote de arquivos a partir do qual o pip pode gerar a instalação. Seu arquivo pyproject.toml contém uma linha que não aparece no repositório público: uma configuração de dados que copia uma pasta chamada cook para dentro do wheel. O arquivo de código-fonte não inclui essa pasta, de modo que a linha extra é o único sinal visível da alteração.
A versão também não correspondia à sua própria tag. A tag v1.107.0 aponta para um commit que indica a versão 1.108.0 em seu arquivo de projeto. A SafeDep descobriu que o arquivo correspondia a um commit posterior na branch principal, com cinco arquivos editados e a pasta adicionada. As edições definiram a versão de volta para 1.107.0 e fixaram os pacotes complementares nos valores usados na release candidate anterior, o que impedia que uma comparação de dependências com a rc2 mostrasse algo incomum.
Os wheels maliciosos foram criados para parecer uma saída normal do processo de lançamento do projeto. Eles listam a mesma versão da ferramenta de build usada nas versões legítimas, e seus registros de arquivo não mostram alterações após a criação. Nenhuma execução pública do GitHub Actions criou ou publicou a versão. A SafeDep verificou 539 execuções entre 09:30 e 12:30 UTC e não encontrou nenhuma que tivesse gerado o pacote. A release no GitHub foi criada cerca de 10 minutos após o envio ao PyPI, por uma conta de bot, e o mesmo atraso ocorreu com a versão 1.106.2. O PyPI não possui atestações de proveniência para as versões 1.107.0, 1.106.2 ou rc2.
A SafeDep afirmou, com confiança moderada a alta, que o pipeline privado de lançamento do projeto criou os wheels a partir de um código-fonte modificado pelo atacante. Segundo a empresa, uma credencial comprometida de mantenedor ou de bot, um branch ou espelho privado, ou a referência que o pipeline utiliza para o build podem explicar as evidências. Já um token do PyPI roubado e usado a partir das máquinas do atacante se encaixa menos bem. Somente os registros do pipeline do projeto podem confirmar como o incidente aconteceu.
Os alvos do roubador
O roubador é executado em todos os processos Python de um host infectado, incluindo aplicações, pip, servidores de linguagem de IDEs e jobs de CI. Ele é organizado em módulos. Um deles lê senhas salvas e o histórico de navegação do Chromium e do Firefox. Outros têm como alvo chaves em ~/.ssh, o histórico do shell, credenciais da AWS, Azure, Google Cloud e Kubernetes, segredos de runners do GitLab e do Jenkins, e credenciais do Terraform. Outro módulo procura tokens e arquivos de configuração usados por ferramentas de programação com IA, incluindo Claude Code, Cursor, Windsurf, Copilot e Gemini CLI, além de tokens do Hugging Face.
O módulo de banco de dados é especialmente sensível para equipes que executam o LiteLLM como proxy. Ele lê a string de conexão com o banco de dados e extrai as tabelas que armazenam as chaves de API dos provedores de LLM. O roubador também consulta o serviço de metadados de instâncias da AWS para obter a identidade da instância e as credenciais de função, além de ler variáveis de ambiente de outros processos em execução.
O que os usuários devem fazer se instalaram o litellm 1.107.0?
Quem instalou o litellm 1.107.0 deve presumir que as credenciais presentes nessas máquinas podem ter sido roubadas. A SafeDep lista os indicadores de comprometimento, incluindo o domínio de envio, os nomes e hashes dos arquivos plantados e um arquivo marcador em /tmp que indica que o roubador já foi executado em um host. Usuários que possuem os três arquivos na site-packages devem removê-los e substituir todas as credenciais que o host poderia acessar.
Questo articolo è stato scritto con l'assistenza dell'IA.
News Factory APP - notizie agentiche per potenziare il tuo SEO e AEO.