Securing a JavaScript based Web Applicaiton

Erlend Oftedal — @webtonull
Web Rebels

Who am I?

But first...

_=[]|[];$=_++;__=(_<<_);___=(_<<_)+_;____=__+__;_____=__+___;$$=({}+"")[_____]+({}+"")[_]+({}[$]+"")[_]+(($!=$)+"")[___]+(($==$)+"")[$]+(($==$)+"")[_]+(($==$)+"")[__]+({}+"")[_____]+(($==$)+"")[$]+({}+"")[_]+(($==$)+"")[_];$$$=(($!=$)+"")[_]+(($!=$)+"")[__]+(($==$)+"")[___]+(($==$)+"")[_]+(($==$)+"")[$];$_$=({}+"")[_____]+({}+"")[_]+({}+"")[_]+(($!=$)+"")[__]+({}+"")[__+_____]+({}+"")[_____]+({}+"")[_]+({}[$]+"")[__]+(($==$)+"")[___]; ($)[$$][$$]($$$+"('"+$_$+"')")() Yosuke Hasegawa - 472 bytes

OWASP Top 10

A1
Injection
A2
Cross Site Scripting (XSS)
A3
Broken Authentication and Session Management
A4
Insecure Direct Object Reference
A5
Cross Site Request Forgery (CSRF)
A6
Security Misconfiguration
A7
Insecure Cryptographic Storage
A8
Failure to Restrict URL Access
A9
Insufficient Transport Layer Protection
A10
Unvalidated Redirects and Forwards

A10 - Unvalidated Redirects and Forwards

A10 - Unvalidated Redirects and Forwards

http://example.com/redirect?url=http://evil.com
http://example.com/login?url=http://evil.com

Twitter september 2010

(function(q) {
  var a = location.href.split("#!")[1];
  if (a) {
    g.location = a;
  }
})
https://twitter.com/#!/web_rebels

https://twitter.com/web_rebels

https://twitter.com/#!http://evil.com

http://evil.com
http://blog.mindedsecurity.com/2010/09/twitter-domxss-wrong-fix-and-something.html

Fixing Unvalidated Redirects and Forwards

A9 - Insufficient Transport Layer Protection

http://www.flickr.com/photos/edgoodwin/

A9 - Insufficient Transport Layer Protection

A8 - Failure to restrict URL access /
A4 - Insecure Direct Object Reference

http://www.flickr.com/photos/56369179@N00/

A8 - Failure to restrict URL access /
A4 - Insecure Direct Object Reference

A7 - Insecure Cryptographic Storage

http://xkcd.com/538/

A7 - Insecure Cryptographic Storage

Server side crypto

A6 - Security Misconfiguration

http://failblog.org/2008/01/03/fail-camera/

A6 - Security Misconfiguration

Open crossdomain.xmls

Alexa top 100 local domains:

26
30
29
Tested 18. mai 2012

What about Access-control-Allow-* ?

And now...

$=[$=[]][(!$+'')[-~-~-~$]+({}+$)[+!'']+($$=(!''+$)[+!''])+(_=(!+$+$)[+$])],$()[(!$+$)[+!'']+(!$+'')[-~-~$]+(!''+'')[-~-~-~$]+$$+_](+!'') Gareth Heyes - 136 bytes

A5 - Cross Domain Request Forgery

Image source: http://www.philatelicdatabase.com/forgeries/stamp-forgeries-1951/

A5 - Cross Domain Request Forgery

Does your server know if the request originated from a page or javascript delivered by itself?

CSRF - Is it really a problem?

CSRF + Cross Domain XHR

function fileUpload(url, fileData, fileName) {
 var fileSize = fileData.length;
 var boundary = "xxxxxxxxx";
 var xhr = new XMLHttpRequest();
 xhr.open("POST", url, true);
 xhr.setRequestHeader("Content-Type", 
   "multipart/form-data, boundary="+boundary);
 xhr.setRequestHeader("Content-Length", fileSize);
 var body = "--" + boundary + "\r\n";
 body += 'Content-Disposition: form-data; name="contents"; filename="'
   + fileName + '"\r\n';
 body += "Content-Type: application/octet-stream\r\n\r\n";
 body += fileData + "\r\n";
 body += "--" + boundary + "--";
 xhr.send(body);
 return true;
}
http://blog.kotowicz.net/2011/04/how-to-upload-arbitrary-file-contents.html

Use anti forgery tokens

$("body").bind("ajaxSend", function(elm, xhr, s){
  if (s.type === "POST") {
    xhr.setRequestHeader('X-CSRF-Token', authentication.csrf_token);
  }
});

A3 - Broken Authentication and Session Management

Image source: @anoras

A3 - Broken Authentication and Session Management

A2 - Cross Site Scripting (XSS)

Image source: @johnwilander

Reflected Cross Site Scripting

Image source: @johnwilander

Stored Cross Site Scripting

Image source: @johnwilander

DOM-based Cross Site Scripting

Image source: @johnwilander

DOM-based - XSS

Unsafe javascript functions

Unsafe jQuery functions

http://twitpic.com/95n3ak

Safe jQuery functions

https://github.com/chrisisbeef/jquery-encoder

jQuery encoder

Templates?

Templating example - Underscore.js

This is all well and good as long as...

For more info - see the OWASP XSS Prevention Cheat sheet

Meanwhile - elsewhere in Norway

<script language="JavaScript" type="text/javascript">
  var qs = location.search.substring(1);
  var nv = qs.split('&');
  var url = new Object();
  for(i = 0; i < nv.length; i++)
  {
    eq = nv[i].indexOf('=');
    url[nv[i].substring(0,eq).toLowerCase()] 
    	= unescape(nv[i].substring(eq + 1));
  }
</script>
<script LANGUAGE="JavaScript">
	document.write('<SCRIPT LANGUAGE="JavaScript" ' +
	 'SRC="'+url['source']+'?"\></SCRIPT\>');
</script>
	
This is the entire HTML file...

Content Security Policy

A1 - Injection

This is the Syringe unicode character - U+1F489

Client Side Injections

Server Side Injections

node.js

var http = require('http');
http.createServer(function (request, response) {
  if (request.method === 'POST') {
    var data = '';
    request.addListener('data', function(chunk) { data += chunk; });
    request.addListener('end', function() {
      var stockQuery = eval("(" + data + ")");
      var price = getStockPrice(stockQuery.symbol);
      …
});
while(1);
http://www.youtube.com/watch?v=3Vwr24MCCVg
http://bishankochher.blogspot.com/2011/12/nodejs-security-good-bad-and-ugly.html

node.js server side eval

JSHint says "eval is evil"...

...I tend to agree...

Mass assignment / overposting

http://chrisacky.posterous.com/github-you-have-let-us-all-down

And finally

<($=[$=[]][(__=!$+$)[_=-~-~-~$]+({}+$)[_/_]+($$=($_=!''+$)[_/_]+$_[+$])])()[__[_/_]+__[_+~$]+$_[_]+$$](_/_) Mario Heiderich - 106 bytes

alert(1)

XEE - XML Entity Expansions

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE foo [ 
	<!ENTITY a "1234567890" > 
	<!ENTITY b "&a;&a;&a;&a;&a;&a;&a;&a;" > 
	<!ENTITY c "&b;&b;&b;&b;&b;&b;&b;&b;" > 
	<!ENTITY d "&c;&c;&c;&c;&c;&c;&c;&c;" > 
	<!ENTITY e "&d;&d;&d;&d;&d;&d;&d;&d;" > 
	<!ENTITY f "&e;&e;&e;&e;&e;&e;&e;&e;" > 
	<!ENTITY g "&f;&f;&f;&f;&f;&f;&f;&f;" > 
	<!ENTITY h "&g;&g;&g;&g;&g;&g;&g;&g;" > 
	<!ENTITY i "&h;&h;&h;&h;&h;&h;&h;&h;" > 
	<!ENTITY j "&i;&i;&i;&i;&i;&i;&i;&i;" > 
	<!ENTITY k "&j;&j;&j;&j;&j;&j;&j;&j;" > 
	<!ENTITY l "&k;&k;&k;&k;&k;&k;&k;&k;" > 
	<!ENTITY m "&l;&l;&l;&l;&l;&l;&l;&l;" > 
]> 
<foo>&m;</foo>
Length: 687,194,767,360 bytes ~ 687 GB

Memory exhaustion - a pile of foo

<?xml version="1.0" encoding="utf-8"?>
<foo>
 <foo>
  <foo>
   <foo>
    <foo>
     <foo>
      ...1 million foos later...
       <foo>
        Hola el mundo
       </foo>
      ...there and back again...
  </foo>
 </foo>
</foo>

		

XXE - XML eXternal Entity Attacks

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE foo [
  <!ELEMENT foo ANY>
  <!ENTITY xxe SYSTEM "/etc/passwd">
]>
<foo>&xxe;</foo>

Some final advice...

Remember...

A Lannister always pays his technical debts

@johnkors

Questions?