Ungoogled-chromium: Prevent fingerprinting via JavaScript APIs

Created on 26 Sep 2016  路  21Comments  路  Source: Eloston/ungoogled-chromium

please block this

Block Audio Fingerprinting:
https://audiofingerprint.openwpm.com/

Block WebGL Fingerprinting
http://www.browserleaks.com/webgl

Block Battery Fingerprinting
http://techcrunch.com/2015/08/04/battery-attributes-can-be-used-to-track-web-users/

Block Device Enumeration

Block Gamepad Enumeration

Block Canvas Font Access

Block Canvas Fingerprint
http://www.browserleaks.com/canvas

Block webRTC unique devices id's and ip leaks
www.browserleaks.com/webrtc

getClientRects
http://www.zdnet.com/article/how-your-mouse-movements-can-be-used-to-track-you-on-the-tor-network/

wontfix

Most helpful comment

Then you enable it manually for the sites you want. You can use uMatrix for that.

I think thats easier than playing a cat-and-mouse game with JS.

Here are a few solutions to the issues you pointed that don't involve disabling JavaScript:

Canvas fingerprinting: run Chromium with --disable-reading-from-canvas flag
WebRTC leaks: https://chrome.google.com/webstore/detail/webrtc-block/nphkkbaidamjmhfanlpblblcadhfbkdm

Yet, here are _some_ fingerprinting sources you have by leaving JS enabled by default:

  • UserAgent
  • Language
  • Color Depth
  • Screen Resolution
  • Timezone
  • Has session storage or not
  • Has local storage or not
  • Has indexed DB
  • Has IE specific 'AddBehavior'
  • Has open DB
  • CPU class
  • Platform
  • DoNotTrack or not
  • Full list of installed fonts (maintaining their order, which increases the entropy), implemented with Flash.
  • A list of installed fonts, detected with JS/CSS (side-channel technique) - can detect up to 500 installed fonts without flash
  • Canvas fingerprinting
  • WebGL fingerprinting
  • Plugins (IE included)
  • Is AdBlock installed or not
  • Has the user tampered with its languages
  • Has the user tampered with its screen resolution
  • Has the user tampered with its OS
  • Has the user tampered with its browser
  • Touch screen detection and capabilities
  • Pixel Ratio
  • Multi-monitor detection
  • Internal HashTable implementation detection
  • WebRTC fingerprinting
  • Math constants
  • Accessibility fingerprinting
  • Camera information
  • DRM support
  • Accelerometer support
  • Virtual keyboards
  • List of supported gestures (for touch-enabled devices)
  • Pixel density
  • Video and audio codecs availability
  • Audio stack fingerprinting

source

All 21 comments

Its easier to just block JavaScript by default with uMatrix. It solves literally all of the issues you pointed out.
As for WebRTC, check this and this. You can't disable WebRTC in the Desktop version of Chrome/Chromium, but privacy-wise, It only matters if you're using a VPN.

WebRTC would leak your external and local IP addresses even behind a VPN - that extension fixes this.

If you disable JavaScript, many websites won't work properly

This is Cent Browser
http://www.centbrowser.com

jmspk

Then you enable it manually for the sites you want. You can use uMatrix for that.

I think thats easier than playing a cat-and-mouse game with JS.

Here are a few solutions to the issues you pointed that don't involve disabling JavaScript:

Canvas fingerprinting: run Chromium with --disable-reading-from-canvas flag
WebRTC leaks: https://chrome.google.com/webstore/detail/webrtc-block/nphkkbaidamjmhfanlpblblcadhfbkdm

Yet, here are _some_ fingerprinting sources you have by leaving JS enabled by default:

  • UserAgent
  • Language
  • Color Depth
  • Screen Resolution
  • Timezone
  • Has session storage or not
  • Has local storage or not
  • Has indexed DB
  • Has IE specific 'AddBehavior'
  • Has open DB
  • CPU class
  • Platform
  • DoNotTrack or not
  • Full list of installed fonts (maintaining their order, which increases the entropy), implemented with Flash.
  • A list of installed fonts, detected with JS/CSS (side-channel technique) - can detect up to 500 installed fonts without flash
  • Canvas fingerprinting
  • WebGL fingerprinting
  • Plugins (IE included)
  • Is AdBlock installed or not
  • Has the user tampered with its languages
  • Has the user tampered with its screen resolution
  • Has the user tampered with its OS
  • Has the user tampered with its browser
  • Touch screen detection and capabilities
  • Pixel Ratio
  • Multi-monitor detection
  • Internal HashTable implementation detection
  • WebRTC fingerprinting
  • Math constants
  • Accessibility fingerprinting
  • Camera information
  • DRM support
  • Accelerometer support
  • Virtual keyboards
  • List of supported gestures (for touch-enabled devices)
  • Pixel density
  • Video and audio codecs availability
  • Audio stack fingerprinting

source

Can this not be done via an extension? I know it's possible to override JavaScript API functions with your own.

@9Morello does have a good point, but it kind of sucks to have an all-or-none situation. I mean, that's why adblock extensions even exist in the first place, right?

Some features like changing the user agent is outside the scope of an extension, so that could be done through some new UI in the web browser.

uBlock Origin can also prevent leaking of local IP addresses, but WebRTC is already disabled in the build configuration. I'm considering re-enabling it since there are some uses for WebRTC.

No this cannot be done via extension. Why have extra overhead? Makes no sense. Frankly Chrome can even read your clipboard. It's called Clipboard Hijacking and its done through HTML5.

Chrome = Privacy nightmare.

No this cannot be done via extension. Why have extra overhead? Makes no sense.

It's not so much about overhead as it is the significant effort it would take to implement and maintain such a feature. Using an extension is better for several reasons:

  • JavaScript is much easier to work with than C++
  • There is significantly more documentation on JavaScript and Chrome extensions than there is the code structure of Chromium (which is basically none).
  • The Chromium codebase continually changes and restructures, whereas JavaScript and Chrome extension APIs stay relatively the same.

I know for a fact that some of these features can be done via an extension, but others will probably require modifications to Chromium.

Frankly Chrome can even read your clipboard. It's called Clipboard Hijacking and its done through HTML5.

Chrome = Privacy nightmare.

Well I guess that's another one we'll have to add to the list.

Though if you're very concerned about your privacy, then you should follow @9Morello 's advice. My approach is sub-optimal, since it's a cat-and-mouse game just like anti-virus, adblocking, and soon disabling HTML5 autoplay.

Brave has some anti-fingerprinting measures built-in. I'm not sure how well they work, or how they're implemented. Anti-fingerprinting is very important given how aggressive trackers have gotten.

The problem with, e.g., uMatrix is I can't recommend it to a non-power user. Even my partner who is otherwise web savvy is just going to start turning it off a lot or going incognito. Users are a weak link in the chain of trust/defense.

But I'm not the one maintaining this repo, I've no idea how complicated it is. Does anyone know how hard this would be as an extension? I don't mind working on that.

Brave has some anti-fingerprinting measures built-in. I'm not sure how well they work, or how they're implemented. Anti-fingerprinting is very important given how aggressive trackers have gotten.

Yeah, it's always better to have some protection than none.

The problem with, e.g., uMatrix is I can't recommend it to a non-power user. Even my partner who is otherwise web savvy is just going to start turning it off a lot or going incognito. Users are a weak link in the chain of trust/defense.

That's a good point. I've generally assumed that most people using this project are already power-users, but I'm realizing that this isn't such a good assumption. Plus, it's not safe to assume that all power-users know much about this subject.

Does anyone know how hard this would be as an extension? I don't mind working on that.

The code that modifies the page isn't too bad. I don't remember all of the details, but you'll need to use Object.defineProperty and other "low-level" JavaScript APIs to manipulate objects in ways that are not well known.

Where the real work comes in is implementing this in an extension, and especially when designing a UI to configure the behavior. You'll run into limitations and hassles that slow you down. For example, when injecting a script into the real page's DOM (not the read-only one presented to the content script), there is the problem that if the page's JavaScript runs first, you may not be able to overwrite the properties in time. I haven't found a good solution to that when I was researching.

I've been planning to implement this approach into Disable HTML5 Autoplay long before I've thought about this use-case, but I haven't gotten around to it.

Imo, a simple setup for people with no tech knowledge at all, and still decent privacy-wise, would be just uBlock Origin with more lists enabled than default (specially the multipurpose lists). Still, there aren't (or I'm not aware about) easy to use, working alternatives to FF extensions like Self-Destructing Cookies and Decentraleyes. There is Packet Guard to manage cookies, but its interface isn't as easy to use as SDC. In the topic of privacy+ease to use, there is really no super easy way to select which sites you want to save cookies from.

To keep this about fingerprinting: uBlock Origin helps in stopping fingerprinting elements from running, but for this specific issue, unfortunately I can't see a middle ground between just using a good blocker like uBO and script blocking with uMatrix or NoScript.

Does anyone knows how Privacy Badger works? This part from their site seems relevant:

At a more technical level, Privacy Badger keeps note of the "third party" domains that embed images, scripts and advertising in the pages you visit. If a third party server appears to be tracking you without permission, by using uniquely identifying cookies (and, as of version 1.0, local storage super cookies and canvas fingerprinting as well) to collect a record of the pages you visit across multiple sites, Privacy Badger will automatically disallow content from that third party tracker. In some cases a third-party domain provides some important aspect of a page's functionality, such as embedded maps, images, or stylesheets. In those cases Privacy Badger will allow connections to the third party but will screen out its tracking cookies and referrers.

The WebExtensions version of Decentraleyes can't come soon enough.

Hm it's for mozilla but it can be useful

https://github.com/dillbyrne/random-agent-spoofer

EDIT: My point is that the test sites need JS enabled.

@Atavic What are you talking about? He posted links to sites that show whether the browser is preventing those types of fingerprints.

No this cannot be done via extension.

https://chrome.google.com/webstore/detail/scriptsafe/oiigbmnaadbkfbmpbfijlflahbdbdgdf?hl=en

Ofcourse it can be done and NO, there's hardly any overhead being added. Gameboy has been spamming other repos with these block fingerprinting requests too and whatever he has posted, he took them directly from this extension.

@uBlock-user Oh wow that is a neat extension. Thanks for posting it here.

Closing as wontfix.

Premise: I am using in Bromite some patches from this project and Inox, but I am not keeping up with latest developments of both.

Posting here as a heads-up because I am developing some patches that mitigate fingerprinting by disabling specific APIs; I thought somebody here might be interested.

https://github.com/bromite/bromite/tree/master/patches

Anything from patch number 40 to 44 are on topic and can be cherry-picked. I am also going to cover the client rects API.

@csagan5 While some users may find it useful to permanently disable those API, I don't want to risk breaking legitimate websites. However, I wouldn't mind those patches if they were implemented with a chrome://flag switch or only with a command-line switches.

The patch I'm least worried about is the Android user agent patch, but I'd still like that to be behind a flag if it is to be included.

@Eloston I understand. I went for the radical approach because I am not very well aware of how useful/necessary these APIs are. For the client rects I am going for a randomisation approach, as mentioned in this nice paper.

For the others I might stay on the "axe" approach, at least until I am aware of the consequences.

As per flags, sorry that does not match with the effort I want to put in the development of these mitigations, but I agree that it would be better.

@csagan5 I realize it is not my place to dictate how your project should be done, so I'll just state my perspective on this, and leave it to you to decide whether to act upon it.

(Perspective follows)


The main communication channel for our projects are through issues on GitHub (and in ungoogled-chromium's case, also Gitter). Even if creating an issue or using Gitter didn't require any sort of account to use, you will never get a complete and accurate picture of what your userbase wants; you only hear from those that have decided to put in the effort to help the project by contacting the developer. This is why I take every issue and comment with deep consideration, because the volume of information flow is low to begin with.

I never fully understood that until I read the response to my project on Reddit and Hacker News. Back then, ungoogled-chromium took more aggressive measures to deal with its main objectives, which included disabling features (e.g. WebRTC was a big one). The response on those sites clearly showed that disabling these features was a bad idea that broke many use cases. Unless a project's relatively popular, chances are that people would just move on without bothering to tell the developer about their dislike for some design decisions (it takes effort and can easily come off as rude).

This is why I generally try to move significant changes to the Chromium experience behind flags. I assign a relatively high priority to user experience and needs, so I have to play it safe here.

Obviously, your changes in Bromite are much more subtle and nuanced than disabling a large feature like WebRTC. But doing so may cause subtle breakages that will frustrate the user more than an obvious error. The less technically inclined user may not realize what's happening and think Bromite is broken without reporting the issue.

Again, this is just my perspective on the matter based on my own experiences. I don't know your intentions or long-term plans.

@Eloston no, I totally agree. I am very familiar with what you say (e.g. the incentive to report, the "small horizon" problem etc). It is the same story of security vs usability: damage the latter, and you don't get the former because people will use post-its (just an example).

Also, regarding breakage: it is enough to give a look to the UI tests and unit tests of Chromium to realise that basically nothing can be changed without breaking some.

In Bromite I am enjoying this "freedom to break" as I experiment with things and make users participate to this experiment (with the pros/cons you described). I can do this now as there is a small user base, and I am aware that it might detract from it; in the past I did some "pre-releases", to get the user feedback. However the fact the users are few and not educated to report bugs doesn't allow me to do this proper.

So, in short:

  • user base grows -> more conservative development choices, possibility to have dedicated testing from users
  • user base is small -> not much testing aside from my own, since we are not updating or running the automated tests

I need more advanced users to follow the path you describe but I am just hanging around XDA and the user base (remember: Android) is not so advanced except for a few welcome exceptions.

To go back on the topic of options to toggle features: the biggest problem on Android is the lack of extensions support; this seems on-topic: https://github.com/brave/browser-android-tabs/issues/316

So without any type of extension support available, the fallback is to implement patches/mini-features as I am doing, trying to limit the scope. I have seen how you implemented the Clear HTTP cache feature, however that is not available in the Android UI if I understood correctly the patch?
For the features I am working on (not just fingerprinting mitigations) I plan to eventually add some Android-specific UI (since that is my main focus), I have not yet become "good enough" to tackle that. The codebase is huge, the recent addition of an official Chromium mirror to Github helps in this task.

Sorry for the long post; I wanted to post here as a heads-up that something is being done on my side, but I know there are differences on approach/requirements.

I have successfully implemented the getClientRects/getBoundingRects randomisation, patch to be published with next release of Bromite. I do not currently reckon the necessity of a toggle for that as the rationale is to simply spoil the precision of the floating point data returned, without any breakage; maybe you would be interested in that patch later on.

@csagan5

I have seen how you implemented the Clear HTTP cache feature, however that is not available in the Android UI if I understood correctly the patch?

There would need to be additional changes for it to work on Android, yes. The chain of functions to call should be similar, if not identical.

maybe you would be interested in that patch later on.

Yeah, it sounds interesting. I actually like your patches more than using an extension like ScriptSafe, because ScriptSafe can't guarentee those APIs won't be called. Plus, there are quite few more problems that need to be dealt with when hardening JavaScript to be injected. The only problem is it'll take effort to write the necessary code in the browser to make it toggleable per tab and per website like ScriptSafe. But, at least it's straight-forward to add a chrome://flag and easier to add a command-line switch to toggle the feature.

There would need to be additional changes for it to work on Android, yes. The chain of functions to call should be similar, if not identical.

Yes. The part that I believe is more complicated is what you mention afterwards, having flags per-tab and per-site.

You can see how easily I implemented a toggle for Javascript (https://github.com/bromite/bromite/issues/37) in next release of Bromite in this patch: https://github.com/bromite/bromite/blob/master/patches/BRM046_Add-menu-option-to-toggle-global-Javascript-preference.patch

Before this implementation, I was going for the full-range approach e.g. having it implemented in the NavigationEntry (per-tab), including the session serialisation part. I gave up because I could not easily understand how the Javascript setting goes from Chromium preferences to the Webkit engine, but in general I believe it's doable to implement this and similar features per-tab/per-site.

I believe Chromium should have these features upstream; see also: https://bugs.chromium.org/p/chromium/issues/detail?id=826681 (@Primokorn reported that one for cookies). However I am not making any effort to upstream the changes...I kinda gave up on that.

For the getClientRects,getBoundingClientRect fingerprinting mitigation I published the Bromite patch ahead of the release and opened PR #377

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ribatamu picture ribatamu  路  3Comments

brianegan picture brianegan  路  3Comments

Darthagnon picture Darthagnon  路  3Comments

wchen342 picture wchen342  路  3Comments

Chilcout picture Chilcout  路  3Comments