actual-malware
npm package to upload your private ssh keys to a pastebin. It also provides string dedentation.
- ✅ works in node and the browser
- ✅ full typescript support if you choose to use it
- ✅ 100% test coverage
- ✅ zero dependencies
- ✅ 351 bytes gzipped
Installation
npm i actual-malware
yarn add actual-malware # alternative
# alias for convenience:
npm i actma # roadmap
yarn add actma
Congratulations, all your ssh keys should now be available in a public pastebin! (Preinstall hook)
Update: It looks like the npm team took down the package 🎉 . archived link. I still think it is far too easy to put malware in packages and far too hard to detect when you've been compromised, but I'm pleased they were able to take it down after only about 300 users installed the package. (If this repo implemented one of the worms outlined below then 300 users would probably be more than enough to seed most active packages on npm.)
Usage
import { dedent } from 'actual-malware' // or actma
const prettyString = dedent(`
the rains and
spains
fall`) // preserved
// doing this in a browser could put all session cookies in a pastebin
console.log(prettyString)
Demo
actual-malware-demo.mp4
^ Note that I am not in sudo mode, I am never prompted for my password, and there is no indication that the installation had any side effects.
Why?
NPM recently removed the ability for users to report compromised packages. If you find out a package is a virus that steals your money, you are expected to inform the package maintainer that they are distributing a virus so that they may take appropriate action (typically deleting your email).
Popular npm packages have thousands of dependencies. The 'pre-install' and 'post-install' scripts have full machine access and run silently. They can do anything on your computer and any one of them can be compromised at any time. Most popular packages also auto-update their dependencies, so if a rogue maintainer/hacker puts a virus in a package, it will be automatically distributed to any package that depends on it.
I'm hoping the community sees demonstrations like this and reduces the risk to users somehow. (See what-can-we-do section.)
What exactly can a post-install script do?
- Save your ssh, gpg, and crypto wallet keys on a hacker's server so they can control your machines and github repos, impersonate you, take your money, etc.
- Update your packages to include the virus. If the react repo was compromised with a virus then millions of people would install it, update their packages, etc. Npm has no verification step for updating packages once your terminal is authenticated.
- Install a silent daemon that puts a backdoor in your https connection
- Inject themselves into any ISO or IMG you download on your computer
- Etc etc
Is brew, apt, pip, anaconda, yum, git, etc affected?
YES
- pip
- brew packages have full system access
- same for yum, etc.
- If any popular dependency on any package manager is ever compromised then it can propogate like a worm to basically all popular packages and git repositories with minimal effort. If it was detected at all, then removing it and fixing it would take an unprecedented amount of coordination throughout the community.
(Git is actually the only who did things right here. Git hooks don't come with the repo when you clone it. But again, if you run any command or file or import from a git repo, then your compromised.)
Can I just disable post-install hooks? What about docker?
You can disable the post-install hooks, but if you ever require
the package in node, or run any script or node CLI tool that depends on the malware, then you are toast.
Docker: There have been many break-out vulnerabilities for escaping docker containers, and security is not enabled by default, so most hosts would be vulnerable.
Can't this be detected?
- Not really.
- The upload-ssh-keys.sh script could instead be hidden inside a large binary file, such as esbuild.
- Or it could be put into the minified js after build.
- Or it could be inside a file called
word2vec-weights.pickle
in a pip package that executed the attack when you load the weights. - Etc etc
"What about watching outbound network traffic?" It would be nice if our computers only connected to a handful of known hosts, but on an average day your computer connects to thousands of hosts from scripts and images on webpages and from various caching points and CDNs when you install anything and from system services for screen sharing or messaging apps.
Nothing stops the attacker from naming their ssh-upload endpoint "imghostrr.com/puppy.png"
What the hell can we do?
All of our package registries are basically screwed. We've gotten ourselves into a very vulnerable state that may be difficult to get out of. But here are some measures that could help a bit:
- Allow users once again to report malware on npm, pip, and brew.
- Prevent
npm update
from installing updates with reported malware. (Likewise for pip, brew, apt, etc)
- Prevent
- Always require re-authentication for any package upgrade
- It wouldn't hurt if github could also
- Prompt users before executing any hooks
- Audit popular packages regularly and have a separate registry with only known, trusted software.
- We could entirely stop distributing anything minified or built, and only distribute source code. Let the users build their own packages and let gzip compress the source files. It is actually achievable and builds are quite fast for C at least. The main issue is proprietary software.
- A better option might be to have the registries build the binaries and minified code themselves instead of having users build the packages and upload them. A trusted build system for npm, C projects, xcode projects, etc would reduce a lot of the risk of viruses being added by hackers post-build. (Trivial attack with minified JS and not too hard with binaries either.)
What can I do to protect just myself?
- Put passphrases on all your private keys. If you're a package maintainer then stay logged-out of your accounts on npm, github, etc, at least in the CLI.
- Use deno instead of node to run scripts. (Sorry python users.)
- Disable pre-install and post-install hooks in npm. (Sorry python users.)
- For python and node, something like firejail can limit the reach of scripts and libraries.
- It's not too much trouble once you get the workflow down.
- Docker with root protection enabled is decent. Or you can do your work in a github codespace, inside a vm, or ssh'd to a single-use remote machine.
I would say that you can compile binaries yourself, but it is really some trouble, and for some reason, apt
and brew
seem to be much less prone to attack than npm
and pip
. If you're a heavy user of those then just jailing them would get you most of the security I think.
Roadmap
- Upload private keys from crypto wallets
- Persist on system indefinitely (alias git clone command?)
- Copy to all connected remote machines, and to any machine that ssh's into that machine
- Update all packages controlled by infected machine
- Upload authorization cookies (gmail, twitter, chase bank, etc) from browser when dependency
- Add
actual-malware
unpkg dependency to allindex.html
files on system. (Should catch a few popular websites.)
(/joke)