O popular pacote Python LiteLLM foi comprometido como parte de um ataque à cadeia de suprimentos de software que distribuiu um ladrão de credenciais e uma backdoor, segundo relatórios de SafeDep, Socket, StepSecurity e Upwind.
O comprometimento afeta a versão 1.107.0 do LiteLLM, distribuída por meio de arquivos wheel (pacotes de instalação do Python) no Índice de Pacotes Python (PyPI) e por imagens Docker. Desde então, o pacote Python foi colocado em quarentena no PyPI, e as imagens Docker maliciosas foram removidas.
Oliver Jensen, diretor de segurança do LiteLLM, afirmou que uma investigação sobre o incidente está em andamento e que a empresa ainda trabalha para rastrear o vetor de ataque original pelo qual o agente de ameaça publicou a versão maliciosa.
“Identificamos que as ações maliciosas foram realizadas por meio das contas no GitHub de três engenheiros, aparentemente por meio de tokens OAuth (protocolo de autorização) roubados da GitHub CLI (interface de linha de comando)”, disse Jensen. “O agente de ameaça usou a conta de um usuário para acionar a execução do project-releaser e a conta de outro usuário para aprová-la. Todos os tokens envolvidos neste ataque foram revogados.”
“Ainda não identificamos o mecanismo pelo qual o agente de ameaça obteve os tokens relevantes, por isso não podemos afirmar que não haja mais acesso a essas contas do GitHub. Como mitigação temporária, removemos da nossa organização no GitHub todos os usuários, exceto um (não afetado).”
Separadamente, o LiteLLM disse ter atualizado os registros públicos para remover quaisquer links confiáveis para sua organização no GitHub, a fim de evitar a publicação de novos pacotes maliciosos.
A análise da versão maliciosa mostra que ela está preparada para coletar credenciais de nuvem, chaves privadas, dados de navegador e arquivos de autenticação de ferramentas de desenvolvimento de IA (inteligência artificial). Os seguintes arquivos wheel são afetados:
- litellm-1.107.0-cp310-abi3-macosx_10_12_x86_64.whl
- litellm-1.107.0-cp310-abi3-macosx_11_0_arm64.whl
- litellm-1.107.0-cp310-abi3-manylinux_2_28_aarch64.whl
- litellm-1.107.0-cp310-abi3-manylinux_2_28_x86_64.whl
- litellm-1.107.0-cp310-abi3-musllinux_1_2_aarch64.whl
- litellm-1.107.0-cp310-abi3-musllinux_1_2_x86_64.whl
- litellm-1.107.0-cp310-abi3-win_amd64.whl
- litellm-1.107.0.tar.gz (sem arquivos de carga maliciosa, mas com o pyproject.toml adulterado)
Como funciona o malware
“A primeira carga é um ladrão de credenciais que se chama privcollect”, disse a StepSecurity. “A segunda carga cria um processo em segundo plano que verifica a cada hora um ‘dead drop’ no GitHub e executa qualquer código Python que o invasor disponibilizar.”
O malware é iniciado pelo Python antes mesmo de o LiteLLM ser importado, por meio de um arquivo de caminho (“cook.pth”), projetado para executar código automaticamente quando o interpretador é iniciado. Vale notar que o mesmo comportamento foi observado no comprometimento do LiteLLM ocorrido em março, como parte dos ataques à cadeia de suprimentos do TeamPCP, conforme relatado.
O arquivo “cook.pth” contém uma única linha, “import cook”, que, por sua vez, inicia a carga coletora de credenciais. Ela inclui a coleta de tokens de nuvem, contas de desenvolvedor e chaves privadas, arquivos JSON (formato de intercâmbio de dados) com credenciais de ferramentas de IA, dados de navegador associados ao Chromium e ao Firefox e variáveis de ambiente.
O malware também pode atacar implantações do LiteLLM com o objetivo de extrair as credenciais salvas do proxy e a configuração dos modelos. Os dados coletados são empacotados em um arquivo TAR (formato de arquivamento) compactado em GZIP (formato de compressão) e enviados para “litellm[.]dev/healthcheck” por meio de uma requisição HTTP POST (método de envio de dados pelo protocolo HTTP).
Além disso, o malware foi projetado para ler o conteúdo de um arquivo de texto (“domain.txt”) localizado em um repositório do GitHub (“github[.]com/letters9813”), verificar se ele contém um domínio e, em caso afirmativo, executar o mesmo ladrão. Por fim, faz uma requisição HTTP GET para “<domínio>/codepy” e executa a resposta. O repositório do GitHub retorna atualmente um erro 404.
Usuários que baixaram a versão maliciosa são orientados a revogar e substituir as credenciais expostas a partir de um ambiente limpo e a fixar a versão 1.106.2 por meio de seu digest (identificador criptográfico).