
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.
| Componente | Pacotes uuid32-utils, colorinal e termncolor no repositório PyPI, com entrega do malware ZiChatBot em sistemas Windows e Linux. |
| Vetor | Instalação de pacotes Python aparentemente legítimos; termncolor atuava como pacote de aparência benigna ao declarar colorinal como dependência. |
| Impacto | Execuçã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. |
| Prioridade | Localizar 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ões | Os pacotes foram enviados ao PyPI em uma janela curta entre 16 e 22 de julho de 2025 e posteriormente removidos do repositório. |
| Artefatos | Droppers terminate.dll no Windows e terminate.so no Linux; caminho Linux /tmp/obsHub/obs-check-update; persistência via Registro do Windows e crontab. |
| IoCs | Nomes de pacotes uuid32-utils, colorinal e termncolor; arquivos terminate.dll e terminate.so; diretório /tmp/obsHub/ e binário obs-check-update. |
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.
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.
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.dllapós importação de pacote Python comprometido. - Hosts Linux com
terminate.so,/tmp/obsHub/obs-check-updateou entradas suspeitas emcrontab. - Pipelines que resolveram
termncolore instalaramcolorinalcomo dependência transitiva. - Ambientes com tráfego permitido para APIs do
Zulip, especialmente quando a aplicação não é usada legitimamente pela organização.
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,colorinaloutermncoloremrequirements.txt, lockfiles, caches dopip, logs de CI/CD e imagens de contêiner. - Criação, carregamento ou remoção rápida de
terminate.dllem Windows eterminate.soem Linux. - Arquivo
/tmp/obsHub/obs-check-updatee novas entradas emcrontabsem mudança operacional documentada. - Processos Python modificando persistência local ou iniciando comunicação REST com
Zulip. - Tráfego para APIs do
Zulipa partir de servidores, agentes de build ou usuários que não utilizam a plataforma.
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,colorinaletermncolorde 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 emcrontab. - 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
Zulippor processos Python.
0 Comentários