Typosquat of popular Ethereum package on npm sends private keys to remote server
On Aug 3, 2023 Phylum’s automated risk detection platform alerted us to a series of suspicious publications on npm
. The attacker eventually published final versions of two packages: a typosquat of a popular cryptocurrency library and a dependency that contained the malicious code buried deep in a large file that most developers would never bother looking at. The malicious code did not change the primary functionality of the cryptographic library. Instead, it makes an HTTP request to a Chinese server containing the user’s private key - game over for the unsuspecting user.
--cta--
As of publication, these packages are still active on npm
with hundreds of downloads, and anyone using these packages should consider their cryptographic security compromised. Join us as we uncover the details of this ongoing attack.
The legitimate packages
First, we have the ethereum-cryptography
package, a Javascript library with over 1.2M downloads that contains cryptographic primitives for Ethereum, the second most popular cryptocurrency behind Bitcoin.
A critical dependency for ethereum-cryptography
is @noble/curves
which contains a Javascript implementation of elliptic curve cryptography and is also a popular package on npm
with about 400K downloads.
First, we note that @noble/curves
contains a warehouse of cryptographic functions across about 100 files. Each of these files contain sophisticated code that most developers would never bother to scrutinize, making it an ideal hiding place. It is critical to point out that a compromise to or an error in any function in any of these libraries can have devastating effects, and @noble/curves
puts on the top line that its library is independently audited. This attacker exploited this trust to trick unsuspecting users into using his typosquatted fakes, instead of the legitimate packages.
The Typosquats
Our attacker @jackshanyeshuzi
initially published @jackshanyeshuzi/curvess
a typosquat of @noble/curves
- note the extra s
in the typosquat - in his own namespace. (As an aside, changing the name from curves
to curvess
has no impact at all since the attacker chose to namespace his package.) Comparing the README.md
files between the two packages on npm
shows them to be nearly identical, but the careful observer would notice the important differences between the numbers of dependencies (1 vs. 2), dependents (132 vs. 1), and downloads (388K vs. 45).
With his spoofed cryptographic library in place, he published his first typosquat of the legitimate Ethereum package, ethereum-cryptographyy
- note the extra y
at the end on 3 August 2023. Shortly thereafter he published ethereum-cryptographyyy
This package appeared to be nearly identical to the legitimate package except for changing the dependencies as we can see by comparing line 4 this example.
His package.json
file also updates the dependency.
About 12 hours after jackshanyeshuzi
published the first typosquat ethereum-cryptographyy
, he unpublished it. Besides the false start typosquat package ethereum-cryptograph
which he published and unpublished within an hour, his main line of development was in @jackshanyeshuzi/curvess
and ethereum-cryptographyyy
. Most of his versions are tests of minor changes, but his main goal can be seen in v.1.1.3 of @jackshanyeshuzi/curvess
in the file abstract/weierstrass.js
. Consider the first few lines of the legitimate package:
and compare with his version (line 10)
An import of the http
library has no legitimate use in this file. Farther down in the legitimate file, we find the function prepSig
:
Comparing with the attacker’s version, we see that his code is identical to the code in the legitimate @noble/curves
implementation of Weierstrass, except that his ships the user’s private key off to wallet.cba123.cn
before going about its business.
A quick lookup shows the key harvesting server in China, as confirmed by ICANN:
Later versions show him trying to cover his tracks with an amateur attempt at obfuscation:
It is easy to see that this code performs the same task.
Conclusions
The Phylum research team reported this package shortly after it was published, and as of this writing, the packages are still available on npm
with around 500 downloads so far. Any compromise of a private key in a cryptographic system should nullify any expectation of security. Moreover, this attacker did not directly change or weaken any of the cryptographic primitives in his spoofed library. He merely stole the keys by shipping them off to his server while the cryptographic code was going about its business.
This should serve as a reminder to remain vigilant about the open-source code that your organization imports, and especially all of their dependencies.
All of the versions of all of the package as of this publication are in the timeline below.
Development timeline for typosquatted packages
2023-08-03T15:26:15.068Z | Published @jackshanyeshuzi/curvess v.1.1.0 |
---|---|
2023-08-03T15:32:44.526Z | Published ethereum-cryptographyy v.2.1.2 (only version of this package) |
2023-08-03T15:48:31.165Z | Published ethereum-cryptographyyy v.2.0.0 |
2023-08-04T02:20:45.551Z | Published ethereum-cryptograph v.1.0.3 (only version of this package) |
2023-08-04T03:00:38.944Z | Unpublished ethereum-cryptograph |
2023-08-04T03:01:01.269Z | Unpublished ethereum-cryptographyy |
2023-08-04T04:33:40.216Z | Published @jackshanyeshuzi/curvess v.1.1.1 |
2023-08-04T04:50:56.734Z | Published ethereum-cryptographyyy v.2.0.1 |
2023-08-04T05:58:13.285Z | Published @jackshanyeshuzi/curvess v.1.1.2 |
2023-08-04T06:00:33.479Z | Published ethereum-cryptographyyy v.2.0.2 |
2023-08-04T06:12:38.752Z | Published @jackshanyeshuzi/curvess v.1.1.3 |
2023-08-04T06:13:18.219Z | Published ethereum-cryptographyyy v.2.0.3 |
2023-08-04T06:23:43.895Z | Published @jackshanyeshuzi/curvess v.1.1.4 |
2023-08-04T06:24:21.969Z | Published ethereum-cryptographyyy v.2.0.4 |
2023-08-04T07:21:23.191Z | Published @jackshanyeshuzi/curvess v.1.1.5 |
2023-08-04T07:22:12.317Z | Published ethereum-cryptographyyy v.2.0.5 |
2023-08-04T07:34:44.749Z | Published @jackshanyeshuzi/curvess v.1.1.6 |
2023-08-04T07:35:17.807Z | Published ethereum-cryptographyyy v.2.0.6 |
2023-08-04T07:44:47.288Z | Published @jackshanyeshuzi/curvess v.1.1.7 |
2023-08-04T07:45:09.946Z | Published ethereum-cryptographyyy v.2.0.7 |
2023-08-04T07:55:44.509Z | Published @jackshanyeshuzi/curvess v.1.1.8 |
2023-08-04T07:56:23.687Z | Published @jackshanyeshuzi/curvess v.1.1.9 |
2023-08-04T07:56:47.192Z | Published ethereum-cryptographyyy v.2.0.9 |