Friday, February 17, 2012

Intro to Chrome addons hacking: fingerprinting

tldr; Webpages can sometimes interact with Chrome addons and that might be dangerous, more on that later. Meanwhile, a warmup - trick to detect addons you have installed.

While all of us are used to http / https URI Schemes, current web applications sometimes use other schemes including:

Tough questions

Throughout the years, there have always been questions on how documents from these schemes are supposed to be isolated from each other (think of it like a 2nd order Same Origin Policy). Typical questions include:
  • Can XMLHttpRequest from http:// document load a file:// URL? And the other way around?
  • Can document from https:// load script from http://? Should we display SSL warning then?
  • Can http:// document have an iframe with view-source: src?
  • Can data: URI access the DOM of the calling http:// document?
  • Can file:// URL access a file:// from upper directory (it's not so obvious)
  • What about:blank?
  • How to handle 30x redirections to each of those schemes?
  • What about passing Referer header across schemes?
  • Can I across schemes? Would window.postMessage() work?
  • and many, many more issues
In general, all this questions come down to:
  • How should we isolate the schemes from each other?
  • What information is allowed to leak between scheme boundaries?
Every single decision that has been made by browser vendors (or standard bodies) in those cases has consequences to security. There are differences in implementation, some of them very subtle. And there are subtle vulnerabilities. Let me present one example of such vulnerability.

Meet chrome-extension://

Google Chrome addons are packaged pieces of HTML(5) + Javascript applications. They may:
  • add buttons to the interface
  • launch background tasks
  • interact with pages you browse
  • ...
All extension resources are loaded from dedicated chrome-extension:// URLs . Each extension has a global unique identifier. For example, 
chrome-extension://oadboiipflhobonjjffjbfekfjcgkhco/help.html is URL representing help.html page from Google Chrome to Phone (you can try it, if you have this extension enabled).

Extension interact with web pages that you visit and have access to their DOM, but the Javascript execution context is separated (they cannot call each other Javascript code - and for a good reason). 

However even in this separation model there is still place for page <-> addon cooperation. Malicious HTTP pages might interact with addons in various ways. One simple example is addon enumeration.

Finding your addons one by one

With a little Javascript code I can easily test if you're using a certain Chrome addon. Give me a list of most popular extensions and I'll test all of them in milliseconds. Why would I want that as an attacker?
  • to fingerprint your browser (ad networks love this)
  • to start attack against a certain known vulnerable addon (wait for the next post for this ;) )
See demo of Chrome addons fingerprinting. (src here)


The trick is dead simple:
var detect = function(base, if_installed, if_not_installed) {
    var s = document.createElement('script');
    s.onerror = if_not_installed;
    s.onload = if_installed;
    s.src = base + '/manifest.json';
detect('chrome-extension://' + addon_id_youre_after, function() {alert('boom!');});
Every addon has a manifest.json file. In http[s]:// page you can try to load a script cross-scheme from chrome-extension:// URL, in this case - the manifest file. You just need the addon unique id to put into URL. If the extension is installed, manifest will load and onload event will fire. If not - onerror event is there for you.
Update: TIL the technique was already published by @albinowax. Cool!

This is just one simple example of punching the separation layer between addons and webpages. There are more coming. Stay tuned.


Lirodon said...

Or, otherwise just block those freeloaders who use Adblock Plus.

Abraham Williams said...

Starting with Chrome v18 developers should specify manifest_version 2.

"Resources inside of packages using manifest_version 2 or above are blocked by default, and must be whitelisted for use via this property."

linuxonian said...

Ia all probability if we are using Adblock Plus we dontr want the adds so we are unlikley to be bother by wet behind the ear comments like that of   "Lirdon" below  anything that blocks content you do not want is a BIG PLUS  for the web user 

Tom Dickson-Hunt said...

It doesn't detect addons that are loaded unpacked or from a custom-packed extension file, presumably because they don't have conventional fingerprints. Not that pertinent for most people, but useful if you want to disguise your usage of an addon.

Paul Hutchinson said...

Doesn't work for me: Chrome 18.0.1025.108 beta-m

Fixed already?

Software Coder said...

You can do this with Firefox as well. Internet Explorer does not enumerate plugins but you can do the same thing, and even turn other PLUGINS off. For IE, you have to install a plugin, to get access to the plugin list. I have done it.

basement dad said...

 Or, even better. Block those people who want to decline other's people right to choose, how to surf the web.  You wan't to block everyone who uses a text-based client like lynx/links etc? Go f*** yourself. I use whatever addon I want to use. No one can dictate me how I prefer to render webpages.

Dick Dunbar said...

Anyone know why about:blank is so bloody slow on IE ?
Microsoft: I'm not looking for an explanation, I'm looking for an empty page :-)

Smitty said...

Freeloader? One can only stand to look at so many Evony, seizure inducing, geocities level coding and poorly composed iStock hack job ads before you go mad.

There is little time between finding a poorly done hack ad campaign so undesirable that it makes me want to NOT use their services and deciding that the slow loading bloat makes me want to bill them for wasting my bandwidth.

My ABP has blanket settings to block more or less everything... with exceptions for a handful of websites I think are worthy and quality enough to allow them to get paid to show me ads. If the webmaster of a site is going to be so childishly petty to block me outright from word go, then I will simply vote with my clicks and not go there. Ever. That action and mindset alone tells me enough about the quality of the content therein that I will NOT allow them the benefit of showing me advertisements.

CardcaptorRLH85 said...

It works here in Chrome version 19.0.1068.1 dev-m.  There may be some setting (or extension)  that stops it from working on your browser.

pogue972 said...

I came across a site recently that had, I feel, a good alternative to both arguments for and against Adblock.  It just has a nice little message at the top that says "Hey, we see you're using adblock.  That's cool, but would you consider unblocking us?"

But, out of curiosity I hunted around to try and discover how they were detecting Adblock and found a Javascript file that contains the text, but I can't make heads or tails of it.  Unfortunately, Pastebin doesn't seem to have line numbers on it, but ctrl+f for "can't" (w/o quotes) 

This is the site

Corndig said...

 If you don't view their ads, then you are a liability not an asset.  Your clicks cost them money, and they're glad to see you gone.

gardendecors lebanon said...

A very nicely done post. You’ve
made your post interesting to read. Awaiting to see more…

ttalang said...

With Chrome 40, we get the following error "denying load of chrome-extension://addon_Id_you_r_after/manifest.json. Resources must be listed in the web_accessible_resources manifest key in order to be loaded by pages outside the extension.".

However for this seems to be a good way for detecting whether a chrome extension published by you is installed on a users browser or not. So that you can prompt user to install it accordingly.

Joana Kane said...