In this report we detail our novel user tracking mechanism that leverages Trust Tokens

NOTE

We are preemptively filing this report in case the Brave Team proceeds with an implementation of the Trust Token API. This bug currently affects browsers that have implemented the Trust Token, which does NOT include Brave.

It does, however, affect other Chromium-based browsers. We have filed a bug with their team (https://bugs.chromium.org/p/chromium/issues/detail?id=1273211).

Trust Tokens remain visible in the DevTools UI (under the Application Tab) on Brave, but this storage is inaccessible from a visited website. Any network requests made for Trust Tokens are treated as regular network requests, thus disabling Trust Token issuance.

The Brave Team currently uses the Privacy Pass protocol for their ad confirmations [8], but has disabled elements of Chrome’s Privacy Sandbox [9].

Also, the EFF’s statement regarding the Trust Token API calls it “a big win for users with disabilities” [10].

DESCRIPTION OF THE ISSUE

The new Privacy Sandbox provides Trust Tokens as a cross-origin mechanism for communicating trust signals for the current browser / user. Since Trust Tokens enable a transfer of information that could lead to privacy loss, the Chrome team has recognized the potential for abuse and attempted to limit it [1].

However, despite the defenses in place, we have found that Trust Tokens offer a new persistent storage mechanism, keyed to the origin, which opens the possibility of tracking vectors that can be exploited similar to previously reported approaches [2, 3, 4].

The main concept behind Trust Token-based tracking is to generate and store a unique combination of trust tokens across origins. This combination of origins can then be used to identify a user across visits in both, 1p and 3p scenarios as long as the tokens don’t expire.

More importantly, using document.hasTrustToken() instead of token redemption ensures that reading the identifier does not consume tokens, and hence does not require an issuer to a) re-issue exhausted tokens, or b) actively participate in the reading phase across 3p sites.

This tracking can be triggered by third-party JS used on any website the user visits, by redirecting them accordingly through a series of origins. These origins serve different trust tokens and hence create their own entries in the browser’s Trust Token Store. An attacker with a set of N-origins can create an N-bit browser identifier that is unique to each browser. An attacker can even use their own set of origins without any interaction with the set of issuers.

The use of document.hasTrustToken() for the described attack scenario has the following characteristics that make it interesting.

  1. Using document.hasTrustToken() does not incur the network overhead required for redemption, and does not involve the issuer’s consent. This scenario is, hence, a blind spot in considerations to prevent token exhaustion. [7]

    • With the number of calls for document.hasTrustToken() capped at 2 for every top-level origin page visit, the corresponding bits that can be read per visit is also capped at 2, hence halving the number of required redirections (e.g., the site can reconstruct a 32-bit identifier through 16 redirections).
  2. Trust Token entries are bound to the origin, instead of the site. This allows a new entry to be set for each subdomain under a given site, and even each port under a given subdomain.

    • Both, the API Explainer [5] and the Design Doc [6] indicate the imposition of per-site issuer limits. These limits can be trivially circumvented by hosting on N/2 domains (N being the number of bits for an identifier).
  3. The set of origins used for writing the ID need not be the same set of origins that read the ID. In other words, this mechanism can be used for cross-site tracking.

  4. Third party Javascript Files and third-party iFrames can perform both the read and write operations.

    • Malicious iFrames can exhaust the issuer association limit for the top-level origin and for other iFrames.
  5. Through our initial experiments we have found that our technique can write a 32-bit identifier in ~3 seconds and read a 32-bit identifier in ~1 second. This could be further reduced by incorporating immutable browser fingerprints for reducing the amount of entropy that needs to be recovered from the Trust Tokens (as demonstrated in [3]).

STEPS TO REPRODUCE

The fingerprinting attack has two phases:

  1. Generate and store the browser ID, and

  2. Read the stored browser ID.

The origins used in either phase can be mutually exclusive sets. The attacker needs control of multiple sites OR multiple subdomains under a given site OR multiple ports under a given domain.

For simplicity, in the description below we assume that the attacker owns multiple sites – (a.com, b.com, c.com, d.com) for writing a new ID, and (e.com, f.com) for reading an existing ID, and an additional site (x.com) to check if an ID already exists.

The top-level origin that a user is trying to visit may either be an attattacker-controlled domain OR some benign domain with attacker-controlled third-party JS.

1. Write Browser ID

  1. When a user visits a website, the attacker initially checks for an existing ID by querying document.hasTrustToken(https://x.com).
1. If the promise returned is True, an ID has already been written. The following steps can be skipped.
2. If the promise returned is False, no ID has yet been written. The following steps can be executed.
  1. The attacker will then set the ID through redirections of the top-level document. While doing so, it considers a 4-bit vector would be formed by the domains :
  • a.com → Bit 1
  • b.com → Bit 2
  • c.com → Bit 3
  • d.com → Bit 4
1. Redirect from the initial website to a.com. Issue Trust Tokens for a.com and b.com.
2. Redirect from a.com to c.com. Issue Trust Tokens for c.com and d.com.
3. Redirect to the initial website. Issue Trust Token for x.com, indicating that a browser ID has been written.

The existence of a Trust Token from a given origin can indicate a (0/1) bit. Say, the browser ID to be written is 1010. The attacker can then issue trust tokens for a.com and c.com, but skip issuance for b.com and d.com.

2. Read Browser ID

  1. When a user visits a website, the attacker initially checks for an existing ID by querying document.hasTrustToken(https://x.com).
1. If the promise returned is True, an ID exists, and we can proceed to read it in the steps that follow.
2. If the promise returned is False, no valid ID exists. We need to first trigger the writing mechanism from the previous phase.
  1. The attacker will then read the ID through redirections of the top-level document.
1. Redirect from the initial website to e.com. Check if Trust Tokens have been set using document.hasTrustToken(`https://a.com`) and document.hasTrustToken(`https://b.com`).
2. Redirect from e.com to f.com. Check if Trust Tokens have been set using document.hasTrustToken(`https://c.com`) and document.hasTrustToken(`https://d.com`).
3. Redirect to the initial website. The browser ID has been retrieved.

During the redirections, a query for document.hasTrustToken() that returns True translates to a 1 bit and a query that returns False translated to a 0 bit.

ACTUAL RESULT

Chromium-based browsers leak the availability of Trust Tokens from one website to a third party. This helped develop a new 3p tracking mechanism.

EXPECTED RESULT

Trust Tokens should only be exposed to sites that the issuer expects to work with. The information leak resulting from this mechanism should be minimized.

REPRODUCES CONSISTENTLY?

Every Time.

BRAVE VERSION

None so far.

Chromium Version: >=84+ [stable, beta, and dev], including Google Chrome, Microsoft Edge, and Opera.

Operating System: all


Bibliography


[1] Trust Token API Explainer: Cross-site Information Transfer https://github.com/WICG/trust-token-api#cross-site-information-transfer

[2] Chromium Bugs: Issue 1096660: Security: Favicon cache can reveal entries through a leaky side channel, that can be used for tracking and fingerprinting of the browser.
[Online]. [Accessed: 22-Nov-2021]

[3] K. Solomos, J. Kristoff, C. Kanich, and J. Polakis, “Tales of Favicons and Caches: Persistent Tracking in Modern Browsers – NDSS Symposium,” presented at the Network and Distributed System Security Symposium (NDSS), 2021, pp. 1–19 [Online]. [Accessed: 22-Nov-2021]

[4] P. Syverson and M. Traudt, “HSTS Supports Targeted Surveillance,” in 8th USENIX Workshop on Free and Open Communications on the Internet (FOCI 18), Baltimore, MD, 2018, pp. 1–8 [Online]. [Accessed: 22-Nov-2021]

[5] Trust Token API Explain: Mitigation: Per-Site Issuer Limits

[6] “Chrome Design Doc: Trust Token API,” Google Docs. [Online]. [Accessed: 22-Nov-2021]

[7] Trust Token API Explainer: Security Considerations: Trust Token Exhaustion

[8] Brendan Eich on Twitter: Available: https://twitter.com/BrendanEich/status/1290099098184384512 [Accessed: 24-Nov-2021]

[9] Brave, “Why Brave Disables FLoC,” Brave Browser, 12-Apr-2021. [Online]. [Accessed: 24-Nov-2021]

[10] B. Cyphers, “Don’t Play in Google’s Privacy Sandbox,” Electronic Frontier Foundation, 30-Aug-2019. [Online]. [Accessed: 24-Nov-2021]

CREDIT INFORMATION

Mir Masood Ali, PhD student, University of Illinois at Chicago

Binoy Chitale, MS student, Stony Brook University

Mohammad Ghasemisharif, PhD Candidate, University of Illinois at Chicago

Chris Kanich, Associate Professor, University of Illinois at Chicago

Nick Nikiforakis, Associate Professor, Stony Brook University

Jason Polakis, Assistant Professor, University of Illinois at Chicago

1 Like