Liran Tal

Developer Advocate at Snyk

Malicious Modules on npm

A Series of Unfortunate Events

@liran_tal
@liran_tal
github.com/lirantal

Liran Tal

Developer Advocate

01

Black Clouds in Node.js Security

02 

|

|

03 

|

Common Security Vulnerabilities

Silver Linings in Node.js Security

Black Clouds & Silver Linings
in Node.js Security

@liran_tal

@liran_tal

"Installing an average npm package introduces an implicit trust on 79 third-party packages and 39 maintainers, creating a surprisingly large attack surface"

- Zimmerman et. al.

@liran_tal

npm's Heavy reuse

Spring web framework

10 transitive dependencies

Express web framework

47 transitive dependencies

@liran_tal

src: https://snyk.io/opensourcesecurity-2019

@liran_tal

The Biggest Repository

Invites big risks

Lucrative attack playground

Open and free-to-publish ecosystem

Difficult to counter-measure

- Disconnect between SCM and Registry

- Commiter !== Publisher

@liran_tal

Small World with High Risks:
A Study of Security Threats in the npm Ecosystem

src: www.usenix.org/conference/usenixsecurity19/presentation/zimmerman

2019

@liran_tal

"a small, linear increase in direct dependencies leads to a significant, super-linear increase in transitive dependencies"

@liran_tal

"transitive dependencies of an average package has increased to a staggering 80 in 2018"

@liran_tal

"for the majority of the time the reach of vulnerable unpatched code is between 30% and 40% is alarming"

@liran_tal

Typosquatting Attacks

Compromised Accounts

Social Engineering

Malicious Modules

@liran_tal

Malicious Modules

time

Jan 2017

crossenv

@liran_tal

$ npm install crossenv --save

crossenv    !=   cross-env

@liran_tal

crossenv/package.json

@liran_tal

crossenv/package-setup.js

@liran_tal

coffescript      or      coffe-script 

coffeescript

@liran_tal

src: https://snyk.io/vuln

@liran_tal

How did we find out about this malicious crossenv package?

post-install script ✅

call-home base64 payload ✅

@liran_tal

@liran_tal

Malicious Modules

time

Jan 2017

crossenv

May 2018

getcookies

@liran_tal

getcookies

parse http headers for cookie data

or does it... ?

@liran_tal

getcookies

http-fetch-cookies
                └── express-cookies
                                        └── getcookies

 

@liran_tal

getcookies

mailparser                               

    └── http-fetch-cookies
                └── express-cookies
                                        └──getcookies

 

@liran_tal

@liran_tal

@liran_tal

@liran_tal

Reset the buffer

Load JavaScript code

Execute code

@liran_tal

@liran_tal

Observation 1

security by code review has to be on-point ALL THE TIME, where-as attackers only have to get lucky ONCE

@liran_tal

Malicious Modules

time

Jan 2017

crossenv

May 2018

getcookies

Jul 2018

eslint-scope

@liran_tal

eslint-scope 3.7.2

malicious package published

@liran_tal

What's going on?

@liran_tal

@liran_tal

@liran_tal

Who depends on eslint-scope?

babel-eslint

eslint

webpack

@liran_tal

npm invalidates all tokens

<= 2018-07-12

 

estimated potential ~4,500 accounts  were compromised 

@liran_tal

Observation 2

eslint-scope published an npm package, but actors had no github repository access so the source code varied between github and the published npm package

@liran_tal

How does something like this happen?

@liran_tal

Compromised Contributors ?

14%

compromised npm modules

Compromised Contributors ?

src: https://github.com/ChALkeR/notes

@liran_tal

Compromised Contributors ?

20%

npm total monthly downloads

express

react

debug

moment

request

Compromised Contributors ?

@liran_tal

@liran_tal

Compromised Contributors ?

koa

maintainers

password

had their password set to

Compromised Contributors ?

@liran_tal

Compromised Contributors ?

1409

users

had their password set to

their username

Compromised Contributors ?

@liran_tal

Compromised Contributors ?

11%

users

had their password set to

previously leaked password

Compromised Contributors ?

@liran_tal

61% of packages on npm
could be considered
abandoned

@liran_tal

Malicious Modules

time

Jan 2017

crossenv

May 2018

getcookies

Jul 2018

eslint-scope

event-stream

Nov 2018

@liran_tal

src: https://snyk.io/blog/a-post-mortem-of-the-malicious-event-stream-backdoor

@liran_tal

some popular packages reach more than 100,000 other packages via
direct or transitive depenencies

@liran_tal

event-stream reached 5,466 packages when it was compromised and it's not even considered "top" influence

@liran_tal

Observation 3

due to the increased use of transpilers, reviewing and comparing source code between actual source to distributed is a real problem

@liran_tal

Dependency Management

@liran_tal

(CC BY-NC-SA 2.0)

@liran_tal

Rolling out security fixes

The security blindspot of
lockfile attack vectors

@liran_tal

src: https://npmjs.com/package/lockfile-lint

@liran_tal

Common Security
Vulnerabilities

Code Injection

@liran_tal

The npmjs Ecosystem

Silver Linings in
Node.js Security

@liran_tal

2FA Enabled accounts
since npm >= 5.5.1

6.89%

@liran_tal

Enable 2FA
since npm >= 5.5.1

$ npm profile enable-2fa

2FA successfully enabled. 
Below are your recovery codes,
please print these out. 

@liran_tal

- auto release ?

- tokens are global for all packages

👉 https://github.com/nodejs/package-maintenance/issues/244

Enable 2FA
caveats 😞

@liran_tal

Find vulnerabilities in
open source dependencies

@liran_tal

What if security was easier?

@liran_tal

"a sign of a healthy security community that reports vulnerabilities at a very good pace, keeping up with the growth of the ecosystem"

@liran_tal

The Security WG

@liran_tal

|

Developer's security awareness
Fix vulnerabilities in our open source deps
Join the Node.js Security WG 🤗

Black Clouds & Silver Linings
in Node.js Security

@liran_tal

@liran_tal
github.com/lirantal

Liran Tal

Developer Advocate

Develop Fast. Stay Secure.
Thank you

Made with Slides.com