Vulnerability allows cross-browser tracking in Chrome, Firefox, Safari, and Tor
Tags: webdev, privacy, javascript, opensource
Published: 2021-05-13 19:28:40


*In this article we introduce a scheme flooding vulnerability, explain how the exploit works across four major desktop browsers and show why it's a threat to anonymous browsing.*

![Exploiting custom protocol handlers for cross-browser tracking in Tor, Safari, Chrome and Firefox](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dwtcjvswhog1dql4fxoi.png "Scheme flood vulnerability overview")

**DISCLAIMER:** FingerprintJS does not use this vulnerability in our products and does not provide third-party tracking services. We focus on stopping fraud and support modern privacy trends for removing third-party tracking entirely. We believe that vulnerabilities like this one should be discussed in the open to help browsers fix them as quickly as possible. To help fix it, we have submitted bug reports to all affected browsers, created a live demo and have made a <a href="https://github.com/fingerprintjs/external-protocol-flooding" target="_blank" rel="noopener">public source code repository</a> available to all.

### **Test the vulnerability on our <a href="https://schemeflood.com/"  target="_blank" rel="noopener">live demo site</a>. Works on desktop browsers only.**

<br>

In our research into anti-fraud techniques, we have discovered a vulnerability that allows websites to identify users reliably across different desktop browsers and link their identities together. The desktop versions of Tor Browser, Safari, Chrome, and Firefox are all affected.

We will be referring to this vulnerability as scheme flooding, as it uses custom URL schemes as an attack vector. The vulnerability uses information about installed apps on your computer in order to assign you a permanent unique identifier even if you switch browsers, use incognito mode, or use a VPN.

## Why does this matter? 

The scheme flooding vulnerability allows for third party tracking across different browsers and thus is a violation of privacy.

### No cross-browser anonymity

Cross-browser anonymity is something that even a privacy conscious internet user may take for granted. Tor Browser is known to offer the ultimate in privacy protection, though due to its slow connection speed and performance issues on some websites, users may rely on less anonymous browsers for their every day surfing. They may use Safari, Firefox or Chrome for some sites, and Tor for sites where they want to stay anonymous. A website exploiting the scheme flooding vulnerability could create a stable and unique identifier that can link those browsing identities together.

Even if you are not a Tor Browser user, all major browsers are affected. It’s possible to link your Safari visit to your Chrome visit, identify you uniquely and track you across the web.

### Profiling based on installed apps

Additionally, the scheme flood vulnerability allows for targeted advertisement and user profiling without user consent. The list of installed applications on your device can reveal a lot about your occupation, habits, and age. For example, if a Python IDE or a PostgreSQL server is installed on your computer, you are very likely to be a backend developer. 

Depending on the apps installed on a device, it may be possible for a website to identify individuals for more sinister purposes. For example, a site may be able to detect a government or military official on the internet based on their installed apps and associate browsing history that is intended to be anonymous.

### Unknown impact on the web

This vulnerability has been possible for more than 5 years and its true impact is unknown. In a quick search of the web, we couldn’t find any website actively exploiting it but we still felt the need to report it as soon as possible.

## How does it work? (technical overview)

Note: You may skip this section if you are not interested in the technical implementation details. The source code of the <a href="https://schemeflood.com/" target="_blank" rel="noopener">demo</a> application is available on <a href="https://github.com/fingerprintjs/external-protocol-flooding" target="_blank" rel="noopener">GitHub</a>.

The scheme flooding vulnerability allows an attacker to determine which applications you have installed. In order to generate a 32-bit cross-browser device identifier, a website can test a list of 32 popular applications and check if each is installed or not. On average, the identification process takes a few seconds and works across desktop Windows, Mac and Linux operating systems. 

To check if an application is installed, browsers can use built-in custom URL scheme handlers. You can see this feature in action by entering skype:// in your browser address bar. If you have Skype installed, your browser will open a confirmation dialog that asks if you want to launch it. This feature is also known as deep linking and is widely used on mobile devices, but is available within desktop browsers as well. Any application that you install can register its own scheme to allow other apps to open it.

![An example of a custom URL scheme handler for Zoom](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/71z0lr0okuvq7avl74ee.png "Scheme handler")

In order to detect if an application is installed, we can test an application's custom URL scheme and then check if a popup has been shown. 

To make this vulnerability possible, the following steps are required:

1. Prepare a list of application URL schemes that you want to test. The list may depend on your goals, for example, if you want to check if some industry or interest-specific applications are installed.
2. Add a script on a website that will test each application from your list. The script will return an ordered array of boolean values. Each boolean value is true if the application is installed or false if it is not.
3. Use this array to generate a permanent cross-browser identifier. 
4. Optionally, use machine learning algorithms to guess your website visitors’ occupation, interests, and age using installed application data.

The steps above may sound easy, but most browsers have safety mechanisms in place designed to prevent such exploits. Weaknesses in these safety mechanisms are what makes this vulnerability possible. A combination of <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS" target="_blank" rel="noopener">CORS policies</a> and browser window features can be used to bypass it.

The actual implementation of the exploit varies by browser, however the basic concept is the same. It works by asking the browser to show a confirmation dialog in a popup window. Then the JavaScript code can detect if a popup has just been opened and detect the presence of an application based on that.

Let’s walk through some of the browser differences.

### Chrome

Of the four major browsers impacted, only Chrome developers appear to be aware of the scheme flooding vulnerability. The issue has been discussed on the <a href="https://bugs.chromium.org/p/chromium/issues/detail?id=1096610" target="_blank" rel="noopener">Chromium bug-tracker</a> and is planned to be fixed soon.

Additionally, only the Chrome browser had any form of scheme flood protection which presented a challenge to bypass. It prevents launching any application unless requested by a user gesture, like a mouse click. There is a global flag that allows (or denies) websites to open applications, which is set to false after handling a custom URL scheme.

![An example of how the Chrome browser protects against scheme flooding by requiring a user gesture](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j62wlimstn1mutp7t8ji.png "Scheme flood protection in Chrome")

However, you can use Chrome extensions to reset this flag and bypass the scheme flood protection. By <a href="https://chromium.googlesource.com/chromium/src/+/refs/heads/main/chrome/browser/external_protocol/external_protocol_handler.h#125" target="_blank" rel="noopener">specification</a>, extensions need to be able to open custom URLs, such as mailto: links, without confirmation dialogs. The scheme flood protection conflicts with extension policies so there is a loophole that resets this flag every time any extension is triggered.

The built-in Chrome PDF Viewer is an extension, so every time your browser opens a PDF file it resets the scheme flood protection flag. Opening a PDF file before opening a custom URL makes the exploit functional.

### Firefox

Every time you navigate to an unknown URL scheme, Firefox will show you an internal page with an error. This internal page has a different origin than any other website, so it is impossible to access it because of the <a href="https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy" target="_blank" rel="noopener">Same-origin policy</a> limitation. On the other hand, a known custom URL scheme will be opened as about:blank, whose origin will be accessible from the current website.

![An example of how you can check if an application is installed based on the origin URL](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vcp793rhx0oi1t8vvsyr.png "URL scheme examples")

By opening a popup window with a custom URL scheme and checking if its document is available from JavaScript code, you can detect if the application is installed on the device.

### Safari

Despite privacy being a main development focus for the Safari browser, it turned out to be the easiest browser of the four to exploit. Safari doesn’t have scheme flood protection and allows to easily enumerate all installed applications.

The same-origin policy trick as used for the Firefox browser was used here as well.

### Tor Browser

Tor Browser has confirmation dialogs disabled entirely as a privacy feature, which, ironically, exposed a more damaging vulnerability for this particular exploit. Nothing is shown while the exploit runs in the background, contrasting with other browsers that show pop-ups during the process. This oversight allows the exploit to check through installed applications without users even realizing it.

Tor Browser is based on the Firefox source code, so the Same-origin policy trick was used here as well. But because Tor Browser does not show pop-ups, we used the same-origin policy trick with iframe elements instead.

By creating an iframe element with a custom URL scheme and checking if its document is available you can check if the application is installed or not.

![An example of how you can use an iframe element to check if an application is installed](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v8iex3eoikf53jf2yz4y.png "iframe element with custom URL scheme")

Of the four browsers, the scheme flooding vulnerability takes the longest to successfully run in Tor.  It can take up to 10 seconds for each application to be checked due to Tor Browser policies. Still, the exploit can be made to work in the background and track you over a longer browsing session. If you left a Tor Browser window on a web page only for 4 minutes, it could be enough to expose your identity.

It’s possible to remove the 10-second limitation by running each application test inside a user-triggered gesture. A fake captcha is an ideal candidate: 24 characters entered by a user makes it possible to reset that 10-second limitation 24 times in a row and enumerate 24 installed applications instantaneously.

## Conclusion

The exact steps to make the scheme flooding vulnerability possible may vary by browser, but the end result is the same. Getting a unique array of bits associated with a visitor’s identity is not only possible, but can be used on malicious websites in practice. Even Tor Browser can be effectively exploited by tricking a user into typing one character per application we want to test.

Until this vulnerability is fixed, the only way to have private browsing sessions not associated with your primary device is to use another device altogether. 

By submitting these bug reports, writing this article and building our demo application, we hope that this vulnerability is fixed across all browsers as soon as possible.

## Useful links

* <a href="https://schemeflood.com/" target="_blank" rel="noopener">Demo</a> (works only on desktop)
* <a href="https://github.com/fingerprintjs/external-protocol-flooding" target="_blank" rel="noopener">Repository with all sources</a>
* <a href="https://bugs.webkit.org/show_bug.cgi?id=225769" target="_blank" rel="noopener">Bug report for Safari</a>
* <a href="https://bugs.chromium.org/p/chromium/issues/detail?id=1096610" target="_blank" rel="noopener">Bug report for Chrome</a>
* <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1711084" target="_blank" rel="noopener">Bug report for Firefox</a>

If you enjoyed reading this article, consider joining our fully remote team to work on exciting research in online security: [work@fingerprintjs.com](mailto:work@fingerprintjs.com)