Kill all web access to screen/chrome metrics and theme information

NEW
Unassigned

Status

()

defect
7 years ago
5 months ago

People

(Reporter: l702097, Unassigned)

Tracking

(Depends on 1 bug)

Firefox Tracking Flags

(Not tracked)

Details

Attachments

(1 attachment)

(Reporter)

Description

7 years ago
Via scripting and CSS, web sites can monitor information about our screen configuration, browser frame, OS toolbars, and OS theme. They do not need, and have absolutely no right, to be able to record this information. Currently they can, easily and secretly, and can use it as a fingerprint for tracking.

This fingerprint stubbornly persists across any clearing of cache, history, and cookies. Users cannot turn off or restrict this fingerprint without completely disabling scripting. The CSS media queries mechanism always allows recording of some information even with scripting disabled.

However, most of these features can be altered to significantly reduce the fingerprinting information but keep them working, and others can perhaps be compromised. I'd hope the fixes won't be detrimental to legitimate web applications, but I'd still think it's worth it anyway.

Below are the specific issues are I'm reporting, and some proposals for fixing them. In conjunction with that, I've attached an HTML testcase which demonstrates the problem by displaying in real time the unnecessary metrics that web sites can observe.


Screen and chrome sizes:
------------------------

The DOM "window" and "screen" objects let web pages access the following information:

- width and height of the current screen (screen.width, screen.height)
- position of the current screen in a multiple-monitor setup (screen.left, screen.top)
- width and height of fixed OS toolbars on all sides of the current screen (screen.availLeft, screen.availTop, screen.availWidth, screen.availHeight)
- position of the browser window relative to the origin of the virtual desktop (window.screenX, window.screenY)
- width and height of the browser window (window.outerWidth, window.outerHeight)
- inner width and height of the document (window.innerWidth, window.innerHeight)
- position of the inner frame of the document relative to the origin of the virtual desktop (window.mozInnerScreenX, window.mozInnerScreenY)
- the width and height of the browser chrome on all sides (calculated from the above)
- whether the user is in full-screen mode (window.fullScreen)

Web page access to all of these measurements except for the inner width and height of the document should be killed. Since the properties must exist for backwards compatibility, I'd propose they be re-wired as follows:

screen.left = 0
screen.top = 0
screen.width = window.innerWidth
screen.height = window.innerHeight
screen.availLeft = 0
screen.availTop = 0
screen.availWidth = window.innerWidth
screen.availHeight = window.innerHeight

window.screenX = 0
window.screenY = 0
window.outerWidth = window.innerWidth
window.outerHeight = window.innerHeight
window.mozInnerScreenX = 0
window.mozInnerScreenY = 0
window.fullScreen = false

This will pretend that the browser has no frame, that the screen is the same size as the document, and will deny information about multiple monitors and OS toolbars. The user's full-screen preference, likewise, is none of any website's business (how is it useful?), though it can usually be determined anyway by examining the other properties.

None of the problematic properties is part of an official standard. As far as I've been able to tell, the fact that most of them exist seems to be a historical accident (?). Poor choices in the past led to browsers giving web pages the ability to specify window outer positions and sizes in screen coordinates. Web pages never really wanted to do it this way, but to make it work properly in conjunction with OS toolbars and browser frames, additional properties have been added over time.

There are three ways the numbers are used:

#(1) Positioning of popup windows. The window.open method enables pages to specify the following relevant properties: left, top, width, height, outerWidth, outerHeight, innerWidth, innerHeight.

These would also need to be changed so that width, innerWidth, & outerWidth all specify the inner width; and height, innerHeight, & outerHeight all specify the inner height.

For solving left and top there are two possibilities. The first way is to ignore them completely, and give the window a browser-decided position based on the position of the parent window or the position of the element whose event handler called the window.open method. The second way is to interpret them as a fraction out of the parent window's inner size, and use this to determine the desired center of the popup window, which would then be adjusted to stay within bounds of the screen (or the parent?). This way, it will still be possible for pages to specify where the popup should appear relative to the document in the parent window.

The window object also provides the methods: moveTo, moveBy, resizeTo, resizeBy. The relative methods moveBy and resizeBy are probably not problematic. The absolute methods can be changed to interpret the values the same way as window.open would. So resizeTo would specify the inner size, and moveTo can be ignored, or use a position that's interpreted relative to the parent document. Since in Firefox 7 and later, web pages cannot move or resize windows that weren't created with window.open anyway, this is a minor loss of functionality.

#(2) Reasonable analytics about available space, to inform page layout and design. The only measurement really needed for this for this is the amount of space that the document can use, which is given by window.innerWidth and window.innerHeight. Removing the other information will not prevent these analytics.

#(3) Fingerprinting. This is the most effective use for the screen and chrome sizes. Combining all of the available numbers provides a significant amount of fingerprinting information. The fingerprint is transient but is still usable, and increases the potential effectiveness of other fingerprinting information that it can be combined with.


Even if these variables are squashed, web pages could still obtain some of the metrics by opening a popup window, then observing mouse movement events to determine the thickness of the chrome and the actual position of the popup after it's been fit within the screen bounds, relative to the position of the parent. This is not very practical though, whereas the current situation betrays this information to pages for no cost at all.


screen.colorDepth and screen.pixelDepth:
----------------------------------------

Correct me if I'm wrong; my understanding is that usually screen.colorDepth and screen.pixelDepth are the same, but in some screen driver configurations, one of these is supposed to provide the bits taken up per pixel in the screen buffer, and the other provides the actual number of usable color bits per pixel. (Eg. 24-bit color may use 32-bit ints for fast manipulation, with 8 wasted bits.) I'm not sure which one is which and I haven't observed them to differ in current browsers.

If they can differ in current Firefox, this should be fixed. There's no benefit to web pages being able to obtain information about the bit-depth setting of the screen driver, so it serves only as another piece of tracking entropy. The actual number of usable color bits is useful, though.


CSS media queries:
------------------

Media queries provide access to additional system metrics, some of which duplicate values available via script (like device-width), and some do not (like -moz-touch-enabled).

What is exceptionally dangerous about these properties is that they can be recorded by web pages even with scripting disabled. Disabling scripting is the obvious and common way to stop many tracking features, but there is absolutely no way to prevent extraction of information via media queries.

In addition to the attached testcase which uses JavaScript, I have created a script-free server-side demonstration of the extraction of the values of CSS media queries features:
http://eb0b428b.byethost7.com/

The media queries features regarding themes are absolutely diabolical. They're virtually useless to legitimate web pages and serve only to aid tracking. Maybe they have redeeming value in XUL, but not in web pages, ever.

I think most of the other features should be scrapped for privacy's sake too. We got on for years perfectly well without them. If they are genuinely vital in some way, then at least the unnecessary screen size information should be removed, by setting device-width=width, device-height=height, and device-aspect-ratio=aspect-ratio. This still leaks more information than it should though, and as demonstrated, it cannot be prevented by disabling scripting, so it is especially distressing.

Addition of new CSS media queries features in the future should be considered a security-sensitive issue.


CSS system colors:
------------------

The CSS system color keywords let web pages style elements with colors from the OS theme. This includes such stupendously useless values as the user's desktop background color! Others are vaguely useful on some web pages, maybe? No, probably not.

The real problem is the actual values of these colors are easily extracted as rgb(...) expressions via window.getComputedStyle.

At the very least, these values enable surveillance of the user's OS theme preference. At worst, if a user customizes these colors individually, they may be completely unique and serve as a perfect fingerprint.

I have looked at the specification on what browsers are supposed to return as the computed value for system colors, but it's not clear (to me, at least). From this page: http://www.w3.org/TR/css3-color/, it explains that the computed value for "basic color keywords" and "extended color keywords" is the equivalent hex or rgb(...) value. Then the three sections/headings "basic color keywords", "extended color keywords", and "CSS system colors" are all separate, at the same depth. The implication is then to follow the alternative rule given: "For all other values, the computed value is the specified value". Does that mean return the original color keyword as typed? That would be an easy fix for this, although it could cause problems with scripts do not expect it.

Given that system colors are apparently deprecated by the W3C anyway, and get nearly no use in web pages, another fix would be to hardwire them to a set of basic system-independent colors. UI elements like <button>s and <input>s could retain their OS styling (if desired) via the CSS "appearance" property (which does not seem to allow extraction of its real values (except fonts??)). Some sort of hackery might be required to continue to permit use of the system-default text selection color, though.

Opera has their own interesting hack for this which might be better. For the computed values of system colors they return magic rbga(...) constant values which look like this: "rgba(20, 16, 0, 0.5059)" (that's ButtonFace). These prevent exposure of the underlying values but let the real color be used. The only thing this doesn't do is enable web pages to calculate intermediate colors by averaging the individual RGB components, but that's an obscure and minor loss, given how rarely these color keywords are used at all.


Default color preferences:
--------------------------

Users can set default web page colors via Tools -> Options -> Content -> Colors. These preferences are exposed to web pages, unfortunately. Although they are rarely customized and so less likely to be useful for tracking, it might be easy to fix them. There are already color keywords for them in Firefox, like "-moz-default-background-color". Fixing the computed value for these in the same way as the system color keywords, such as returning a magic value or the keyword itself, would prevent exposure of the real values but still allow these colors to work.


CSS system fonts:
-----------------

The CSS font keywords are probably useful in XUL but virtually junk in web pages, except perhaps to malware trying to imitate the OS UI to trick the user. They also provide problematic theme tracking metrics.

Perhaps it would be better to deprecate these keywords and hard-wire them to neutral defaults?

If these keywords are retained with their normal functionality, preventing reading of their values is very difficult. They are set as single keywords, but they configure a complete style (font-family, font-size, font-style, etc). It is impossible to eliminate measurements of text size by measurements of bounding boxes, and some of the font properties are supposed to return numbers, etc. However, at least the font-family property could be protected by creating special keywords for it. E.g., setting "font: message-box" could configure "font-family: -moz-message-box;" instead of "font-family: Tahoma" (or whatever). This would not harm any legitimate use but it would obfuscate the tracking information somewhat.


Issues with <canvas>:
---------------------

The <canvas> element is an awesome feature. However, it provides another exposure point for recording system colors and fonts. When rendering into an SVG image or canvas, the values of all CSS system colors and font keywords should be set to some system-independent defaults or blocked. Opera blocks system colors entirely (they render as black), though doesn't block system fonts.

The CSS system colors demo in the testcase attempts to read the values both ways, via getComputedStyle and via <canvas>.

The very last demo in the testcase shows how it is possible to take a recordable screenshot of interactive controls via <canvas>, again exposing style information.

Honestly, at this point in my research of this vulnerability I was starting to feel very ill due to it, because the overall amount of fingerprinting possible with all of this horrifies me. It was comforting to read that Firefox tries to get things right, by refusing to render the native theme in a canvas. (https://developer.mozilla.org/en-US/docs/SVG/SVG_as_an_Image#Restrictions, https://developer.mozilla.org/en-US/docs/HTML/Canvas/Drawing_DOM_objects_into_a_canvas). I assume this is also why <canvas> sensibly refuses to honor the platform text anti-aliasing (which is a user preference and would expose the monitor subpixel layout) and doesn't draw scrollbars.

However, it clearly doesn't finish the job. Although it doesn't render advanced themes, the widgets still honor CSS system colors and fonts. The values of these probably enable determination of the native theme anyway, as well as any user customization of the theme, so the theme protection is worthless until it is complete.

It does not really matter if which OS the user has is exposed in the image, because there are too many other ways to expose that anyway, and it is a weak fingerprinting metric, but it is wrong for the browser to expose user preferences, such as colors and fonts, within that OS.


Summary:
--------

Web pages have access to too much system information that does not benefit users and only makes illegitimate surveillance easier. This issue affects all browsers, though people who care most about privacy probably use Firefox. Paradoxically, Firefox provides the most complete set of variables for this sort of thing, making the vulnerability most serious in the browser that should be the best at defending against it. But, it is fixable!

Thank you hugely, whoever and wherever you are, for your immense patience in reading and evaluating this report (and hopefully helping to tackle it).

~~~
(Reporter)

Comment 1

7 years ago
Probably this is a known issues of sorts, but I wanted to jog it to be fixed, and hopefully the testcases are handy.

This issue has always bothered me but now I understand it better I'm losing sleep and appetite over it. I'd like to try to help fix it, rather than just reporting and complaining, but it's far beyond my abilities and I only have 1 gigabyte of ram which I'm told is not enough to compile Firefox. All I can do is ask and hope that the experts care to give it their time. Thanks again for reading.

Here is an online copy of the attachment, since it does not seem to display on Bugzilla itself: http://eb0b428b.byethost7.com/screen.html
We might be able to make window.fullScreen privileged-code-only.

> The media queries features regarding themes are absolutely diabolical

Which ones?  Restricting things like that to not match in content is probably not hard, if you have specific ones that shouldn't match there.  Filing bugs on those, blocking this bug, is probably the way to go.

I wonder how much it would break to neuter window.screen as you suggest...  We might be able to get away with that....
Status: UNCONFIRMED → NEW
Ever confirmed: true
(Reporter)

Comment 3

7 years ago
(In reply to Boris Zbarsky (:bz) from comment #2)
> > The media queries features regarding themes are absolutely diabolical
> Which ones?

Hello.

These are the worst:

-moz-mac-graphite-theme
-moz-mac-lion-theme
-moz-maemo-classic
-moz-windows-classic
-moz-windows-compositor
-moz-windows-default-theme
-moz-windows-theme

It's none of web sites' business which theme people use.

And I think these are probably useless:

-moz-scrollbar-end-backward
-moz-scrollbar-end-forward
-moz-scrollbar-start-backward
-moz-scrollbar-start-forward
-moz-scrollbar-thumb-proportional
-moz-menubar-drag

That's all the -moz ones except -moz-device-pixel-ratio and -moz-touch-enabled.

Honestly, google "-moz-menubar-drag": https://www.google.com/search?q=%22-moz-menubar-drag%22
Whatever it does, not one result relates to using it in practice and the top result turns out to be a test script related to a third-party patch which ultimately removes the feature for privacy reasons! (https://gitweb.torproject.org/torbrowser.git/blob/HEAD:/src/current-patches/firefox/alpha/0009-Limit-device-and-system-specific-CSS-Media-Queries.patch)

> I wonder how much it would break to neuter window.screen as you suggest...  We might be able to get away with that....

I hope so. I think it would be OK. It would have to be a fairly silly website if it bothered to check those values but still depended on them reporting particular frame or screen layout.
Attachment #657114 - Attachment mime type: text/plain → text/html
> These are the worst:

OK.  Could you please file a bug on those, on the style system?
(Reporter)

Comment 5

7 years ago
OK I'll try. I'm not familiar with how things work here so I hope I fill it out right.

Here we go: https://bugzilla.mozilla.org/show_bug.cgi?id=787521
(Reporter)

Updated

7 years ago
Depends on: 787521
(Reporter)

Comment 6

7 years ago
So what now? I'm trying to be patient but these vulnerabilities are serious and need to be fixed.
You need to log in before you can comment on or make changes to this bug.