Pacotes no PyPI entregam malware ZiChatBot usando APIs do Zulip como C2

Pacotes no PyPI entregam malware ZiChatBot usando APIs do Zulip como C2

Três pacotes Python publicados em julho de 2025 combinavam funcionalidade aparente com droppers para Windows e Linux, instalando o ZiChatBot e usando APIs REST do Zulip para receber shellcode.

ComponentePacotes uuid32-utils, colorinal e termncolor no repositório PyPI, com entrega do malware ZiChatBot em sistemas Windows e Linux.
VetorInstalação de pacotes Python aparentemente legítimos; termncolor atuava como pacote de aparência benigna ao declarar colorinal como dependência.
ImpactoExecução de dropper nativo, persistência local e recebimento de shellcode por meio de APIs REST do Zulip usadas como infraestrutura de comando e controle.
PrioridadeLocalizar instalações dos pacotes, remover artefatos de persistência, revisar ambientes de build e rotacionar segredos expostos em hosts ou pipelines que importaram os pacotes.
VersõesOs pacotes foram enviados ao PyPI em uma janela curta entre 16 e 22 de julho de 2025 e posteriormente removidos do repositório.
ArtefatosDroppers terminate.dll no Windows e terminate.so no Linux; caminho Linux /tmp/obsHub/obs-check-update; persistência via Registro do Windows e crontab.
IoCsNomes de pacotes uuid32-utils, colorinal e termncolor; arquivos terminate.dll e terminate.so; diretório /tmp/obsHub/ e binário obs-check-update.
Resumo técnico

A campanha envolveu três pacotes publicados no PyPI com comportamento compatível com ataque de cadeia de suprimentos contra ecossistemas Python. uuid32-utils e colorinal incorporavam payloads maliciosos semelhantes, enquanto termncolor ampliava o alcance ao declarar colorinal como dependência. Esse desenho permite que a instalação de um pacote de aparência comum resulte na execução indireta do componente malicioso, inclusive quando o desenvolvedor não interage diretamente com o pacote que contém o dropper. Os pacotes também implementavam funções compatíveis com suas descrições públicas, o que reduz a chance de suspeita em inspeções superficiais baseadas apenas em funcionalidade observável.

O payload final recebeu o nome ZiChatBot e foi preparado para Windows e Linux. A característica operacional mais relevante é o uso de APIs REST do Zulip como canal de comando e controle, em vez de um servidor C2 dedicado com domínio ou endereço IP próprio. Essa escolha altera a superfície de detecção: conexões para uma aplicação pública de chat podem se misturar a tráfego permitido por políticas corporativas, principalmente em redes onde ferramentas SaaS são autorizadas de forma ampla. O malware recebia shellcode por esse canal, executava o conteúdo no host comprometido e enviava uma resposta de sucesso representada por um emoji de coração, funcionando como confirmação de execução para o operador.

Fluxo técnico

No Windows, a cadeia começa após a instalação de uuid32-utils ou colorinal e a importação da biblioteca em um projeto Python. Nesse momento, o código malicioso extrai uma biblioteca dinâmica chamada terminate.dll e a grava no disco. Quando carregada, a DLL atua como dropper do ZiChatBot, configura uma entrada de execução automática no Registro do Windows e executa uma rotina para apagar o próprio dropper do host. A remoção do componente intermediário reduz evidências estáticas após a instalação, deixando a investigação dependente de telemetria de criação de arquivo, carregamento de módulo, modificação de chaves de inicialização e execução de processos associados ao interpretador Python.

No Linux, o artefato nativo equivalente é terminate.so. O dropper instala o malware no caminho /tmp/obsHub/obs-check-update e cria persistência por meio de crontab. O uso de /tmp é tecnicamente relevante porque muitos ambientes tratam esse diretório como área temporária de baixa criticidade, mas ele pode receber binários executáveis e ser abusado para ocultar payloads sob nomes que simulam atualização ou verificação de componentes. A entrada em crontab permite reexecução periódica ou após eventos definidos pelo invasor, dependendo da configuração aplicada, preservando o acesso mesmo quando o processo inicial gerado pela instalação do pacote é encerrado.

A etapa de comando e controle não depende de infraestrutura dedicada. O ZiChatBot consulta APIs REST do Zulip, obtém shellcode e executa o conteúdo recebido. Essa arquitetura transforma uma plataforma legítima em intermediário operacional, o que dificulta bloqueios baseados apenas em reputação de domínio. O impacto real depende do shellcode entregue em cada host, mas o fluxo confirmado já estabelece capacidade de execução arbitrária pós-instalação, persistência e comunicação de retorno. Como a atribuição não está confirmada, a semelhança de 64% entre o dropper e outro utilizado em atividade associada ao grupo OceanLotus deve ser tratada como pista técnica, não como prova conclusiva de autoria.

Superfície afetada

A superfície principal envolve estáções de desenvolvedores, servidores de build, ambientes de integração contínua, imagens de contêiner e notebooks de análise que instalaram os pacotes uuid32-utils, colorinal ou termncolor durante ou após a janela de publicação entre 16 e 22 de julho de 2025. O risco não se limita a aplicações em produção: ambientes usados para empacotar, testar ou publicar software frequentemente possuem tokens de repositórios, credenciais de nuvem, chaves de assinatura, variáveis de pipeline e acesso a artefatos internos. Um pacote executado durante instalação, importação ou teste pode herdar permissões do usuário local ou do agente de CI/CD.

A presença de termncolor merece atenção específica porque o pacote foi descrito como benigno em aparência, mas introduzia colorinal como dependência. Isso cria um caminho de exposição transitiva: uma equipe pode não encontrar colorinal em manifestos escritos manualmente, mas ainda assim tê-lo resolvido por gerenciadores de dependência, caches locais, lockfiles ou camadas de imagem. A investigação precisa considerar arquivos como listas de dependências, registros de instalação do pip, caches de wheels, imagens baseadas em builds antigos e ambientes virtuais preservados em diretórios de projeto.

  • Hosts Windows que carregaram terminate.dll após importação de pacote Python comprometido.
  • Hosts Linux com terminate.so, /tmp/obsHub/obs-check-update ou entradas suspeitas em crontab.
  • Pipelines que resolveram termncolor e instalaram colorinal como dependência transitiva.
  • Ambientes com tráfego permitido para APIs do Zulip, especialmente quando a aplicação não é usada legitimamente pela organização.
Hunting e telemetria

A busca deve começar pela cadeia de dependências. Em estáções e servidores, inventarie ambientes virtuais Python, caches do pip, lockfiles e históricos de build em busca de uuid32-utils, colorinal e termncolor. Em CI/CD, revise logs de resolução de dependências e artefatos de cache que possam ter preservado wheels baixadas antes da remoção dos pacotes. A ausência dos pacotes no repositório público atual não elimina exposição passada, porque builds reproduzidos a partir de cache local, proxy de pacotes ou imagem interna podem continuar carregando o conteúdo comprometido.

No endpoint Windows, a telemetria útil inclui criação e carregamento de terminate.dll, execução de Python seguida por modificação de chaves de inicialização automática no Registro do Windows, criação de processos incomuns a partir de diretórios de projeto e deleção do arquivo dropper logo após o carregamento. Em Linux, priorize eventos de gravação em /tmp/obsHub/, criação ou alteração de crontab, execução de /tmp/obsHub/obs-check-update e carregamento de terminate.so por processos Python. A correlação temporal entre instalação de pacote, importação de módulo e persistência é mais forte do que qualquer indicador isolado.

Na rede, monitore chamadas a APIs REST do Zulip feitas por hosts que não deveriam usar o serviço ou por processos sem relação com clientes de chat. Como a infraestrutura se apoia em serviço legítimo, o objetivo não deve ser apenas bloquear domínio, mas identificar padrões incompatíveis com uso humano: requisições periódicas, ausência de agente de usuário esperado, execução logo após atividade de Python, volume baixo com respostas acionando execução local e conexões originadas de servidores de build. Quando houver proxy corporativo, extraia método, caminho, usuário autenticado, processo de origem quando disponível e carimbo de tempo para reconstruir a sequência.

  • Referências a uuid32-utils, colorinal ou termncolor em requirements.txt, lockfiles, caches do pip, logs de CI/CD e imagens de contêiner.
  • Criação, carregamento ou remoção rápida de terminate.dll em Windows e terminate.so em Linux.
  • Arquivo /tmp/obsHub/obs-check-update e novas entradas em crontab sem mudança operacional documentada.
  • Processos Python modificando persistência local ou iniciando comunicação REST com Zulip.
  • Tráfego para APIs do Zulip a partir de servidores, agentes de build ou usuários que não utilizam a plataforma.
Mitigação

A resposta deve tratar hosts expostos como potencialmente comprometidos, não apenas como sistemas com dependência vulnerável. Remova uuid32-utils, colorinal e termncolor de ambientes Python, limpe caches de wheels, invalide imagens construídas durante a janela de exposição e force nova resolução de dependências a partir de fontes confiáveis. Em seguida, procure e remova persistência: no Windows, revise chaves de execução automática criadas no período associado à instalação; no Linux, inspecione crontab de usuários e do sistema, além do caminho /tmp/obsHub/obs-check-update. A remoção do pacote sem eliminar persistência pode deixar o ZiChatBot ativo.

A contenção precisa incluir rotação de segredos acessíveis ao contexto de execução afetado. Se o pacote foi instalado em máquina de desenvolvedor, avalie tokens de Git, credenciais de registro de pacotes, chaves SSH, sessões de nuvem e variáveis locais. Se a instalação ocorreu em pipeline, rotacione segredos de CI/CD, credenciais de publicação, tokens de provedores de nuvem e permissões de service accounts usadas pelo job. Também é necessário revisar artefatos produzidos por builds potencialmente comprometidos, porque o host infectado pode ter acessado código, binários, pacotes internos ou metadados sensíveis durante a janela de atividade.

Para reduzir recorrência, aplique controles de cadeia de suprimentos: pinagem de versões, revisão de dependências transitivas, bloqueio de pacotes recém-publicados sem aprovação, uso de repositório proxy com quarentena e geração de SBOM para builds. A detecção deve ser convertida em regras locais para nomes de pacotes, artefatos de dropper, caminho Linux e eventos de persistência. Como o uso de SaaS legítimo como C2 limita a eficácia de listas de bloqueio estáticas, combine telemetria de endpoint, identidade e proxy para validar se comunicações com Zulip partem de usuários e aplicações autorizados.

  • Remover uuid32-utils, colorinal e termncolor de ambientes Python, caches, lockfiles e imagens internas.
  • Investigar e eliminar terminate.dll, terminate.so, /tmp/obsHub/obs-check-update, entradas de Registro do Windows e tarefas em crontab.
  • Rotacionar segredos acessíveis a hosts, ambientes virtuais e pipelines que instalaram ou importaram os pacotes.
  • Recriar builds e artefatos a partir de dependências verificadas, sem reutilizar caches gerados durante a exposição.
  • Criar detecções para instalação dos pacotes, persistência local e uso anômalo de APIs REST do Zulip por processos Python.

Postar um comentário

0 Comentários