3

I'm trying to develop a Firefox extension to protect user security by fighting against browser fingerprinting used for user tracking purposes.

Many, if not all fingerprinting techniques include recording contents of navigator.plugins, navigator.oscpu, navigator.platform, screen resolution, window toolbar height etc. Idea of an extension consists of two parts — first is to randomly filter and permutate plugins and their mime types, and induce randomness in other variables used for tracking; and second is to isolate webpage to prevent it from reusing previously hidden information — like .sol-cookies, utilizing fake E-Tags or anything not discovered yet.

Both methods require reimplementing getters on non-configurable properties of privileged navigator, screen, location objects, and this is the place where I'm stuck.

For example, following straightforward code being entered in Browser Console just does not work:

Object.defineProperty(getBrowser().contentWindow.location, 'href', {
    get: function() {
        return 'foobar';
    }
});

It does not produce any errors, but does not redefine a property either. Moreover, it returns current value of location object for some reason — something that I don't expect from Object.defineProperty.

Replacing location with location.wrappedJSObject makes browser spit out TypeError: can't redefine non-configurable property 'href', identical to what non-privileged code will throw.

I tried to track down what happens when you call Object.defineProperty on something. It seems that it starts with js::obj_defineProperty(), then goes to js::StandardDefineProperty, which in turn does couple of checks, and descends to js::DefinePropertyOnObject, which has huge quantity of checks I don't fully understand yet, and finally ends with js::NativeDefineProperty, where the actual object modification is done.

So, questions are:

  1. Is it possible to redefine location, navigator, screen objects for a page content sandbox entirely, replacing them with some mocked proxies, controlled by my extension?
  2. Or, is it possible to redefine non-configurable property of aforementioned objects?
  3. Or, is it possible to call js::NativeDefineProperty from chrome JavaScript?
  4. Or (less preferred), is it possible to implement binary add-on to expose js::NativeDefineProperty to chrome as a service?

Update: I've got a question at Mozilla IRC, how is location rewriting related to privacy. Just for now all windows in private browsing mode share same cookies, storage and such, so you can still be tracked even in private mode, if you don't reset it too often. How often is too often is a question — ideally, you should reset after each visited site, because each site could mark you. It would be cool, if there was an ability to adjust granularity of private mode — like, separate private windows or tabs one from another.

I thought about tagging all URLs with some kind of tab-unique long random tag — so http://example.com/foo opened in two separate private tabs becomes http://example.com.AYZYXP/foo and http://example.com.QUSOFX/foo. From the browser's point of view, these are two distinct domain names, with their own caching rules, cookies, DOM storage, IndexedDB, FlashPlayer pesistence or anything else. From webpage's point of view it's necessary to keep the impression both tabs are http://example.com/foo, because exposing the tag will defy the idea of tagging — and that's why I need location rewriting.

toriningen
  • 7,196
  • 3
  • 46
  • 68
  • possible duplicate of [Is it possible to overwrite window.location function with a custom function?](http://stackoverflow.com/questions/6478617/is-it-possible-to-overwrite-window-location-function-with-a-custom-function) – Mouser Feb 07 '15 at 08:01
  • @Mouser Thank you for link, but it's not a duplicate — linked question is about hooking `location` from content code, which is indeed not possible because of security considerations. I am asking about doing the same, but **from an extension** — e.g. with chrome privileges, which give full access to browser capabilities and allow for different kinds of hackery. – toriningen Feb 07 '15 at 08:05
  • Sorry missed the part about the extension. However this is core browser behavior, shouldn't this be protected at a very low level? – Mouser Feb 07 '15 at 08:09
  • @Mouser, that's quite what I'm asking about — however it might not be possible through such straightforward means like `Object.defineProperty`, Firefox developers might have reserved an ability for extension authors to customize objects considered protected. Maybe something like calling `js::NativeDefineProperty` via some kind of service or component. – toriningen Feb 07 '15 at 08:14
  • And when talking about security — it's possible for now to entirely destroy the browser from an extension, wipe out the hard drive and burn the computer down with lemons^W an extension. I don't think that telling content script it has address different from real one is *that bad* compared to what extensions can do. – toriningen Feb 07 '15 at 08:17
  • My old company build a browser helper object for IE and a Firefox extension, they handled file downloading and uploading between the website and the client pc. It listened for changes in the file size and modified date and then alerted the user inside the website to upload the new changes. So they had direct access to the hard drive from an extension. However I think formatting needs administrator rights. – Mouser Feb 07 '15 at 08:29
  • @Mouser, damaging or encrypting all your private documents won't require administrator rights, usually. – toriningen Feb 07 '15 at 08:35
  • Rewritten question, so now it's hopefully more clear what I'm trying to do. – toriningen Feb 07 '15 at 10:58

1 Answers1

0

There probably is a way to make one change, and browser will send that to everything and javascript code of window.navigator.blah will return your overridden values. I'll keep my eyes open if I find something like that.

Here's the XPCOM reference: https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XPCOM/Reference/Interface

Im sure if you explore all those you'll find something to override stuff.

But below is one solution where you attach an observer

I'm not sure if you set the request or response headers, if the javascript of window.navigator.blah will return what but its worth a shot, copy paste code anyways. Check it out.

What you do is set up an observer for http-on-modify-request (or maybe others see here for the other observers: MDN :: Observer Notifications - HTTP Requests)

Then in the handler of the observer you do the modifications with setRequestHeader etc, can even setResponseHeader if you do observer for http-on-examine-response.

See this topic, the sample code here spoofs the user agent for the first tab only: How can I change the User Agent in just one tab of Firefox?

Community
  • 1
  • 1
Noitidart
  • 35,443
  • 37
  • 154
  • 323