0

Almost every week you can read about attacks performed through compromised npm libraries. The npm ecosystem is vast and unmanageable and for it-sec people it is frustrating to deal with all the possible threats that come with using npm.

There are a lot of best practices out there how to deal with third party libraries in general, but to be honest, it's not enough in my eyes. Most of these explain how to avoid a breach, but in fact it seems more realistic to discuss an assume-breach-approach.

Regarding npm supply chain attacks I have the impression that they could be performed by either

  • Executing scripts on a machine

or

  • Communicating from within the application

One would now say wait wait there are tons of attacks that can happen through a compromised npm package, like remote code execution, sensitive data stealing, encryption/ransomware and so one (1, 2). You are right, but to make those things work, you have to either run a script on a machine or communicate from within the application with an external threat actor controlled command and control server, e.g.:

  • Perform data exfiltration --> communicating from within the application
  • Spawn a reverse shell --> executing scripts
  • Cryptominer --> executing scripts
  • Ransomware --> executing scripts
  • RCE --> executing scripts
  • Stealing sensitive application data --> communicating from within the application

So bottom line it would be enough to sandbox the running application (e.g. through using a firewall with a whitelist of connections) and block any script execution during the installation process (3)?

In a (very shorten) scenario a developer downloads an arbitrary compromised npm library and installs it on his machine. Then this library is integrated in the developed piece of software which will be build in the CI/CD and finally deployed.
In that case I have three layers on which I need to block scripts and sandbox my application. The hardest part in my eyes is sandboxing the running application on the developer's machine since you need to ponder productivity against security by restricting internet access.

I know all the best practices to work with third party libraries:

  • Using a private repository
  • Scanning the libraries
  • Do not automatically update libraries
  • Using a four-eyes principle when including new libs
  • and so on

And you can also monitor (your) packages looking for possible breach signals (4). But still it might be possible that a compromised library slips into the company. Mistakes happen. But in that case one wants to make sure that no damage can happen, right?

Although this picture is kinda superficial, do I miss a thing? I just want to get a handle on that frustrating topic.

[1] https://snyk.io/blog/snyk-200-malicious-npm-packages-cobalt-strike-dependency-confusion-attacks/

[2] https://www.shiftleft.io/blog/node.js-vulnerability-cheatsheet/

[3] https://medium.com/cider-sec/npm-might-be-executing-malicious-code-in-your-ci-without-your-knowledge-e5e45bab2fed

[4] https://portswigger.net/daily-swig/data-study-reveals-predictors-of-supply-chain-attacks-in-npm-repositories

1 Answers1

0

In my personal opinion, we hear a lot about it, because:

a) the media picks up on it

b) npm and node.js is rather popular according to recent statistics - around 2% of the Web is running Node.js as an app server (that 2% is of total servers, which includes classical web servers like NGINX and Apache!).

The problem is that executing scripts is usually necessary for init scripts and npm or npx (which is practically npm exec) uses scripts in PATH for useful stuff. You can basically use npm like pip and other popular package managers to have a program in your path which you can practically use for various purposes.

I've went a bit into mitigation in this answer here https://security.stackexchange.com/a/256297/204820 The answer is for devDependencies, but apparently this applies to regular dependencies too, and some of the information is very relevant here.

To realistically reduce your attack surface in my personal opinion you should use the least amount of libraries as possible. This law is universal in any programming language actually. I've participated in CTFs where even popular, widely-used (and abused) packages had serious vulnerabilities built in. You will have to maintain the code yourself then, but I think it's a good tradeoff.

Not for there being only two ways for a chain supply attack I'm not so sure. Messing with native APIs, overwriting over packages APIs would also be an option. Babel for example does this for legit purposes, but a possibility for nefarious purposes in third party packages remains.

You should also definitely look into Deno, it promises to solve some of the issues.

Sir Muffington
  • 1,447
  • 2
  • 9
  • 22
  • thank you for your answer. I took a look in your post about devDependencies. I will have to dig deeper in a few things. *"To realistically reduce your attack surface in my personal opinion you should use the least amount of libraries as possible."* I know about this but is this a realistic approach? Regarding frameworks like Angular, React or Vue and having a whole universe of libs it would be a lot of work to have a look in every library it it's really needed, like is-odd, is-even, and so on. – user3240316 Sep 10 '22 at 22:05
  • Of course it's a realistic approach - people write whole HTTPS libraries from scratch in the C programming language ;-) It's definitely doable, but most businesses tend to exploit the already available open source projects to lessen the amount of development needed for their project. This of course is a folly and makes you trust the used libraries, which often are pretty bad. – Sir Muffington Sep 11 '22 at 18:47