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-Tag
s 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:
- 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? - Or, is it possible to redefine non-configurable property of aforementioned objects?
- Or, is it possible to call
js::NativeDefineProperty
from chrome JavaScript? - 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.