I gathered a list of MIME Types from IANA and other sources. Then explicitly used each type to check if navigator.mimeTypes[type] === undefined. I found that I could detect quite a few MIME Types in this way. Including some types that are related to specific application programs and/or peripheral devices.
I maxed the security slider, which disabled Javascript by default and broke the test script. However, after I whitelisted the test script I was able to achieve the same results.
I was testing Tor Browser 5.0.3 for Windows.
Trac: Username: TemporaryNick
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information
Child items ...
Show closed items
Linked items 0
Link issues together to show that they're related.
Learn more.
Or better yet, can you implement it as a mochitest unit test and submit a patch? I think it would be really good for me to start uplifting all of these unit tests to mainline. I figure out a way to make them NOT run by default, but it would be great to have them for testing purposes as I re-factor and uplift other patches.
I uploaded an example, which tests only the application types listed by IANA. There are other types than can be checked and there are an unknown number of types that aren't registered with IANA.
I think the issue is that when you check for a MIME Type in this way, the browser checks with the OS to see whether the MIME Type has been registered. Which MIME Types are registered depends on which application software and/or drivers the user chose to install. My test results were different on different Windows systems. I was, however, testing with a more comprehensive list than that shown in the demonstration.
I think the place to start may be nsMimeTypeArray.cpp, and what happens when you check for a named item. I found someone talking about this type of issue and approaching it via GreaseMonkey script. They mentioned that websites frequently test for some specific MIME Types, so simply blocking named lookups may not be practical.
Good stuff! I thought we already had a defense against this but I could not find anything so far. Arthur: do you have some spare cycles to look at this in October? I fear all the other TBB people are busy with deadline work...
Trac: Priority: normal to major Owner: tbb-team to arthuredelstein Keywords: N/Adeleted, TorBrowserTeam201510 added Status: needs_information to assigned
Good stuff! I thought we already had a defense against this but I could not find anything so far.
It's interesting that navigator.mimeTypes.length == 0. So one would have thought it didn't have any members.
It seems that a partial anti-enumeration design is in place, but only against positional iteration. (As well as setting navigator.mimeTypes.length to 0, all indexes of the form navigator.mimeTypes[0] return undefined.)
But that doesn't stop lookups using an external list of MIME type names.
Good stuff! I thought we already had a defense against this but I could not find anything so far.
It's interesting that navigator.mimeTypes.length == 0. So one would have thought it didn't have any members.
It seems that a partial anti-enumeration design is in place, but only against positional iteration. (As well as setting navigator.mimeTypes.length to 0, all indexes of the form navigator.mimeTypes[0] return undefined.)
It turns out that the mimeTypes list in Firefox comes from two sources: (1) plugins and (2) applications installed on the system. I considered writing a fixed spoof list of mimeTypes, but it was not clear to me which mimeTypes, if any, should be included in such a list.
At this point, Tor Browser strongly discourages the use of plugins (and makes them click-to-play). So it probably makes sense to make the navigator.plugins object appear to be empty to content pages and not show any plugin-associated mimeTypes. This might in principle break a site that requires Flash, but as we (and Mozilla) are discouraging the use of Flash, I'm inclined not to spoof the presence of a "Flash" plugin. Especially as spoofing the presence of Flash might prevent a JS fallback on some sites.
For applications, I think it is reasonable to force websites to assume that any file will be downloaded rather than opened by a helper app.
So, given these conclusions about plugins and applications, I decided to make navigator.mimeTypes appear empty to content pages as well. But I'm open to further discussion.
I bound this behavior to the "privacy.resistFingerprinting" pref, which will hopefully make Mozilla more amenable to accepting it.
The following branch has two commits for review: the implementation and a regression test:
You probably want to do something like #include "nsContentUtils.h" in nsPluginArray.cpp, too (I wonder how you got it compiled without actually).
I don't understand
// TODO: The following line should be active in Firefox 45+ // isnot(navigator.mimeTypes.length, 0, "navigator.mimeTypes array should be 0");
.
What does it mean? We don't need that test yet? If so, why not? Or does it mean we can't run that test right now because XXX would break it? If so what fixes this (Do you have a bug number?)? And does it mean we are save for now with respect to leaking the length of the supported MIME types? If I am guessing right, the answer lies in https://bugzilla.mozilla.org/show_bug.cgi?id=757726 which got resolved as WON'TFIX. If that is true could you add a hint about that in the test explaining what is going on?
You probably want to do something like #include "nsContentUtils.h" in nsPluginArray.cpp, too (I wonder how you got it compiled without actually).
I wonder that too. Apparently it is included in a header file somewhere. I've added #include "nsContentUtils.h" in nsPluginArray.cpp for clarity.
I don't understand
{{{
// TODO: The following line should be active in Firefox 45
// isnot(navigator.mimeTypes.length, 0, "navigator.mimeTypes array should be 0");
}}}
.
What does it mean? We don't need that test yet? If so, why not? Or does it mean we can't run that test right now because XXX would break it? If so what fixes this (Do you have a bug number?)? And does it mean we are save for now with respect to leaking the length of the supported MIME types? If I am guessing right, the answer lies in https://bugzilla.mozilla.org/show_bug.cgi?id=757726 which got resolved as WON'TFIX. If that is true could you add a hint about that in the test explaining what is going on?
mcs/brade: if you have some capacities left and would have a look at this one, too, that would be grand. We might be able to include that one into the alpha as well then.
This looks okay to me and I merged cherry-picked the commits onto tor-browser-38.3.0esr-5.5-2. One question: Is there any reason why you did not add ||ResistFingerprinting() to any AllowPlugins()? I guess only those where you added them are fingerprinting relevant? I wonder if that is going to lead into some confusion though: there may be things doable with plugins if you have fingerprinting defenses enabled (and are allowing plugins) and other things only if you have them disabled. Or are there no such things? I know there are a bunch of users that (need to?) enable Flash but maybe we just don't care about them too much here.
This looks okay to me and I merged cherry-picked the commits onto tor-browser-38.3.0esr-5.5-2. One question: Is there any reason why you did not add ||ResistFingerprinting() to any AllowPlugins()? I guess only those where you added them are fingerprinting relevant? I wonder if that is going to lead into some confusion though: there may be things doable with plugins if you have fingerprinting defenses enabled (and are allowing plugins) and other things only if you have them disabled. Or are there no such things? I know there are a bunch of users that (need to?) enable Flash but maybe we just don't care about them too much here.
I only added ||ResistFingerprinting() to places where information is exposed through the content web APIs. I believe the other functions are only called by Chrome code, so ResistFingerprinting() would always return false.
I think the scope of this ticket is not to disable plugins, but merely to prevent their detection through navigator.plugins. It is in principle still possible to detect plugins by including several of them in a page -- but if we enforce click-to-play, then this is not really a practical attack, I think.