Closed
Bug 1369303
Opened 7 years ago
Closed 7 years ago
Spoof/Disable performance API when 'privacy.resistFingerprinting' is true
Categories
(Core :: DOM: Core & HTML, enhancement, P1)
Core
DOM: Core & HTML
Tracking
()
VERIFIED
FIXED
mozilla56
Tracking | Status | |
---|---|---|
firefox56 | --- | fixed |
People
(Reporter: timhuang, Assigned: timhuang)
References
(Blocks 1 open bug)
Details
(Whiteboard: [fingerprinting][tor][fp:m2])
Attachments
(4 files)
For fingerprinting resistance, we'd like to spoof/disable performance API when 'privacy.resistFingerprinting' is true. * Spoof performance timing API * Disable resource timing * Disable user timing API Some reference prefs * dom.enable_performance * dom.enable_resource_timing * dom.enable_user_timing, this was removed, but we want to add a similar feature back.
Updated•7 years ago
|
Priority: -- → P1
Assignee | ||
Comment 1•7 years ago
|
||
The browser timing attacks can be easily deployed with these APIs. Therefore, there APIs should be spoofed or disabled when fingerprinting resistance is enabled. Following things will happen after 'privacy.resistFingerprinting' been set to true. 1. Every item of performance timing should be spoofed to zero. 2. Disable resource timing API 3. Disable user timing API
Comment hidden (mozreview-request) |
Comment hidden (mozreview-request) |
Comment hidden (mozreview-request) |
Comment 5•7 years ago
|
||
mozreview-review |
Comment on attachment 8874818 [details] Bug 1369303 - Part 1: Adding 'privacy.resistFingerprinting' into worker prefs. https://reviewboard.mozilla.org/r/146208/#review150284
Attachment #8874818 -
Flags: review?(arthuredelstein) → review+
Comment 6•7 years ago
|
||
mozreview-review |
Comment on attachment 8874819 [details] Bug 1369303 - Part 2: Marking the performance timing API always reports 0 and the access of resource timing and user timing becomes NOP when 'privacy.resistFingerprinting' is true. https://reviewboard.mozilla.org/r/146210/#review150288
Attachment #8874819 -
Flags: review?(arthuredelstein) → review+
Comment 7•7 years ago
|
||
mozreview-review |
Comment on attachment 8874820 [details] Bug 1369303 - Part 3: Add a test case for making sure that performance APIs have been correctly spoofed. https://reviewboard.mozilla.org/r/146212/#review150290 ::: browser/components/resistfingerprinting/test/browser/browser_performanceAPI.js:33 (Diff revision 1) > + "loadEventStart", > + "loadEventEnd", > +]; > + > +add_task(async function setup() { > + await SpecialPowers.pushPrefEnv({"set": I'm not sure you need a separate `setup` function here. Maybe merge with `run`? ::: browser/components/resistfingerprinting/test/browser/browser_performanceAPI.js:49 (Diff revision 1) > + for (let time of list) { > + is(content.performance.timing[time], 0, `The timing(${time}) is correctly spoofed.`); > + } > + > + // Check that whether the resource timing API is disabled. > + ok(!content.performance.getEntries, "The performance.getEntries is disabled."); Maybe we should be testing here explicitly for the value expected for `content.performance.getEntriesByType`. Is it `undefined`, `null`, or an empty array? (Unfortunately the expression `!0` returns `true`, though I don't expect that to occur here.)
Attachment #8874820 -
Flags: review?(arthuredelstein) → review+
Comment 8•7 years ago
|
||
(In reply to Tim Huang[:timhuang] from comment #1) > The browser timing attacks can be easily deployed with these APIs. I think some citation is needed for this. What are you trying to prevent exactly? I don't immediately understand what these APIs have to do with fingerprinting?
Updated•7 years ago
|
Flags: needinfo?(tihuang)
Assignee | ||
Comment 9•7 years ago
|
||
There are several fingerprinting concerns around these APIs. a) For performance timing API, it can be used to measure the network latency [1]. The network latency is distinct between different browsers which depends on where and how a browser connects to Web. b) For resource timing API, it is an attack surface of cache-timing attacks [2]. By observing the timing of hits and misses of a given *third-party* resource, an attacker can extract browsing history. However, this requires third party websites have 'Timing-Allow-Origin' in the response header. Given that, this still has a fingerprinting concern. c) For user timing API, attackers can use this to benchmark a given script for measuring a browser's performance pattern. Since the timing of executing the same script could be different depending on the hardware, so this can be used to generate a fingerprinting. [3] shows a similar idea. [1] http://www.darkwavetech.com/fingerprint/fingerprint_latency.html [2] http://sip.cs.princeton.edu/pub/webtiming.pdf [3] http://w2spconf.com/2011/papers/jspriv.pdf
Flags: needinfo?(tihuang)
Updated•7 years ago
|
Whiteboard: [fingerprinting][tor][fp:m1] → [fingerprinting][tor][fp:m2]
Comment 10•7 years ago
|
||
mozreview-review |
Comment on attachment 8874818 [details] Bug 1369303 - Part 1: Adding 'privacy.resistFingerprinting' into worker prefs. https://reviewboard.mozilla.org/r/146208/#review152326
Attachment #8874818 -
Flags: review?(amarchesini) → review+
Comment 11•7 years ago
|
||
mozreview-review |
Comment on attachment 8874819 [details] Bug 1369303 - Part 2: Marking the performance timing API always reports 0 and the access of resource timing and user timing becomes NOP when 'privacy.resistFingerprinting' is true. https://reviewboard.mozilla.org/r/146210/#review152328 I don't like the disabling of methods in Performance interfaces. I suggest to make those methods NOP.
Attachment #8874819 -
Flags: review?(amarchesini) → review-
Comment 12•7 years ago
|
||
mozreview-review |
Comment on attachment 8874820 [details] Bug 1369303 - Part 3: Add a test case for making sure that performance APIs have been correctly spoofed. https://reviewboard.mozilla.org/r/146212/#review152334 Canceling review request
Attachment #8874820 -
Flags: review?(amarchesini)
Comment hidden (mozreview-request) |
Comment hidden (mozreview-request) |
Comment hidden (mozreview-request) |
Assignee | ||
Comment 16•7 years ago
|
||
Comment on attachment 8874819 [details] Bug 1369303 - Part 2: Marking the performance timing API always reports 0 and the access of resource timing and user timing becomes NOP when 'privacy.resistFingerprinting' is true. Arthur, please review these patches again, especially for part 2 and 3.
Attachment #8874819 -
Flags: review+ → review?(arthuredelstein)
Assignee | ||
Updated•7 years ago
|
Attachment #8874820 -
Flags: review+ → review?(arthuredelstein)
Comment 17•7 years ago
|
||
mozreview-review |
Comment on attachment 8874819 [details] Bug 1369303 - Part 2: Marking the performance timing API always reports 0 and the access of resource timing and user timing becomes NOP when 'privacy.resistFingerprinting' is true. https://reviewboard.mozilla.org/r/146210/#review152934 you cannot use nsContentUtils::ShouldResistFingerprinting() in workers as it is. You must have a worker-version of it. ::: dom/performance/Performance.cpp:175 (Diff revision 2) > > void > Performance::GetEntries(nsTArray<RefPtr<PerformanceEntry>>& aRetval) > { > + // We return an empty list when 'privacy.resistFingerprinting' is on. > + if (nsContentUtils::ShouldResistFingerprinting()) { Same issue here. ::: dom/performance/Performance.cpp:190 (Diff revision 2) > void > Performance::GetEntriesByType(const nsAString& aEntryType, > nsTArray<RefPtr<PerformanceEntry>>& aRetval) > { > + // We return an empty list when 'privacy.resistFingerprinting' is on. > + if (nsContentUtils::ShouldResistFingerprinting()) { Same issue here. ::: dom/performance/Performance.cpp:220 (Diff revision 2) > nsTArray<RefPtr<PerformanceEntry>>& aRetval) > { > aRetval.Clear(); > > + // We return an empty list when 'privacy.resistFingerprinting' is on. > + if (nsContentUtils::ShouldResistFingerprinting()) { this is wrong.. getEntriesByName() is exposed to workers. ::: dom/performance/Performance.cpp:282 (Diff revision 2) > > void > Performance::Mark(const nsAString& aName, ErrorResult& aRv) > { > + // We add nothing when 'privacy.resistFingerprinting' is on. > + if (nsContentUtils::ShouldResistFingerprinting()) { This is wrong. Mark() is exposed to workers.
Attachment #8874819 -
Flags: review?(amarchesini) → review-
Comment 18•7 years ago
|
||
mozreview-review |
Comment on attachment 8874820 [details] Bug 1369303 - Part 3: Add a test case for making sure that performance APIs have been correctly spoofed. https://reviewboard.mozilla.org/r/146212/#review152936
Attachment #8874820 -
Flags: review?(amarchesini) → review+
Comment 19•7 years ago
|
||
mozreview-review |
Comment on attachment 8874820 [details] Bug 1369303 - Part 3: Add a test case for making sure that performance APIs have been correctly spoofed. https://reviewboard.mozilla.org/r/146212/#review153174
Attachment #8874820 -
Flags: review?(arthuredelstein) → review+
Comment hidden (mozreview-request) |
Comment hidden (mozreview-request) |
Comment hidden (mozreview-request) |
Comment 23•7 years ago
|
||
mozreview-review |
Comment on attachment 8877460 [details] Bug 1369303 - Part 4: Add a test case for workers to check whether performance API has been correctly spoofed when 'privacy.resistFingerprinting' is true. https://reviewboard.mozilla.org/r/148886/#review153718
Attachment #8877460 -
Flags: review?(arthuredelstein) → review+
Comment 24•7 years ago
|
||
mozreview-review |
Comment on attachment 8874819 [details] Bug 1369303 - Part 2: Marking the performance timing API always reports 0 and the access of resource timing and user timing becomes NOP when 'privacy.resistFingerprinting' is true. https://reviewboard.mozilla.org/r/146210/#review153828 ::: dom/base/nsContentUtils.cpp:2335 (Diff revision 3) > return !isChrome && nsRFPService::IsResistFingerprintingEnabled(); > } > > /* static */ > +bool > +nsContentUtils::ThreadsafeShouldResistFingerprinting() { What about if you merge this function with ShouldResistFingerprinting() ? Just move this code into that function. And add a comment in nsContentUtils.h saying that that function can be used in workers and on main-thread as well. ::: dom/base/nsContentUtils.cpp:2340 (Diff revision 3) > +nsContentUtils::ThreadsafeShouldResistFingerprinting() { > + if (NS_IsMainThread()) { > + return ShouldResistFingerprinting(); > + } > + > + using namespace workers; remove this and simply do: workers::WorkerPrivate* workerPrivate = workers::GetCurrentThreadWorkerPrivate(); ... or add it at the beginning of the file: using namespace mozilla::dom::workers; ::: dom/base/nsContentUtils.cpp:2343 (Diff revision 3) > + } > + > + using namespace workers; > + > + WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate(); > + MOZ_ASSERT(workerPrivate); I prefer: if (NS_WARN_IF(!workerPrivate)) { return false; } ...
Attachment #8874819 -
Flags: review?(amarchesini) → review+
Comment 25•7 years ago
|
||
mozreview-review |
Comment on attachment 8877460 [details] Bug 1369303 - Part 4: Add a test case for workers to check whether performance API has been correctly spoofed when 'privacy.resistFingerprinting' is true. https://reviewboard.mozilla.org/r/148886/#review153830
Attachment #8877460 -
Flags: review?(amarchesini) → review+
Comment hidden (mozreview-request) |
Comment hidden (mozreview-request) |
Comment hidden (mozreview-request) |
Comment hidden (mozreview-request) |
Comment hidden (mozreview-request) |
Comment hidden (mozreview-request) |
Comment hidden (mozreview-request) |
Comment hidden (mozreview-request) |
Comment hidden (mozreview-request) |
Comment hidden (mozreview-request) |
Assignee | ||
Comment 36•7 years ago
|
||
Try looks good. https://treeherder.mozilla.org/#/jobs?repo=try&revision=04b9fee409f2
Keywords: checkin-needed
Comment 37•7 years ago
|
||
Pushed by ryanvm@gmail.com: https://hg.mozilla.org/integration/autoland/rev/f01f4f94f912 Part 1: Adding 'privacy.resistFingerprinting' into worker prefs. r=arthuredelstein,baku https://hg.mozilla.org/integration/autoland/rev/61e7a2279d81 Part 2: Marking the performance timing API always reports 0 and the access of resource timing and user timing becomes NOP when 'privacy.resistFingerprinting' is true. r=arthuredelstein,baku https://hg.mozilla.org/integration/autoland/rev/9c0424ddae1b Part 3: Add a test case for making sure that performance APIs have been correctly spoofed. r=arthuredelstein,baku https://hg.mozilla.org/integration/autoland/rev/2af3f05ec41b Part 4: Add a test case for workers to check whether performance API has been correctly spoofed when 'privacy.resistFingerprinting' is true. r=arthuredelstein,baku
Keywords: checkin-needed
Comment 38•7 years ago
|
||
bugherder |
https://hg.mozilla.org/mozilla-central/rev/f01f4f94f912 https://hg.mozilla.org/mozilla-central/rev/61e7a2279d81 https://hg.mozilla.org/mozilla-central/rev/9c0424ddae1b https://hg.mozilla.org/mozilla-central/rev/2af3f05ec41b
Status: ASSIGNED → RESOLVED
Closed: 7 years ago
status-firefox56:
--- → fixed
Resolution: --- → FIXED
Target Milestone: --- → mozilla56
Comment 39•7 years ago
|
||
Verified on Mac OS 10.12.6 with Nightly 58.0a1 (2017-10-25) (64-bit) Verification steps: 1. Open a new tab, and navigate to http://cnn.com 2. Set parameter privacy.resistFingerprinting to true 3. Open Console, and type the following commands 3a. performance.timing 3b. performance.getEntriesByType('resource').filter(item => item.name.includes("index.html")) 3c. window.performance.getEntries() 3d. performance.getEntries({name : "Begin", entryType: "mark"}) 3e. performance.getEntriesByType("mark") 3f. performance.getEntriesByName("domReady") 3g. performance.mark("mySetTimeout-start"); setTimeout(function() { performance.mark("mySetTimeout-end"); performance.measure( "mySetTimeout", "mySetTimeout-start", "mySetTimeout-end" ); var measures = performance.getEntriesByName("mySetTimeout"); var measure = measures[0]; console.log("setTimeout milliseconds:", measure.duration) performance.clearMarks(); performance.clearMeasures(); }, 1000); Expected results: All the output should be either zero, or empty Actual results: There is one unexpected issue: performance.timing returns this: PerformanceTiming connectEnd: 1509063389918 connectStart: 1509063389918 domComplete: 0 domContentLoadedEventEnd: 0 domContentLoadedEventStart: 0 domInteractive: 0 domLoading: 0 domainLookupEnd: 1509063389918 domainLookupStart: 1509063389918 fetchStart: 1509063390083 loadEventEnd: 0 loadEventStart: 0 navigationStart: 0 redirectEnd: 0 redirectStart: 0 requestStart: 1509063389918 responseEnd: 1509063389918 responseStart: 1509063389918 secureConnectionStart: 1509063389918 unloadEventEnd: 0 unloadEventStart: 0 All these items in the array should equal zero.
Status: RESOLVED → REOPENED
Flags: needinfo?(tihuang)
Resolution: FIXED → ---
Assignee | ||
Comment 40•7 years ago
|
||
The reason why these values do not show a zero is that performance.timing seems to be cached after it has been accessed. The cnn.com will access some fields of performance.timing by itself. So, if you turn 'privacy,resistFingerprinting' after the cnn.com is loaded, it will show cached value, before fingerprinting resistance is on, instead of a zero. Ideally, we should make the 'privacy.resistFingerprinting' works perfectly in every case. However, it is hard to cover them all. So, the ideal behavior for enabling fingerprinting resistance is that turning 'privacy.resistFingerprinting' on before loading any page. What do you think, Ethan and Tom? Should testing follow this principle or we need to fix this?
Flags: needinfo?(tom)
Flags: needinfo?(tihuang)
Flags: needinfo?(ettseng)
Comment 41•7 years ago
|
||
(In reply to Tim Huang[:timhuang] from comment #40) > The reason why these values do not show a zero is that performance.timing > seems to be cached after it has been accessed. The cnn.com will access some > fields of performance.timing by itself. So, if you turn > 'privacy,resistFingerprinting' after the cnn.com is loaded, it will show > cached value, before fingerprinting resistance is on, instead of a zero. > > Ideally, we should make the 'privacy.resistFingerprinting' works perfectly > in every case. However, it is hard to cover them all. So, the ideal behavior > for enabling fingerprinting resistance is that turning > 'privacy.resistFingerprinting' on before loading any page. > > What do you think, Ethan and Tom? Should testing follow this principle or we > need to fix this? I think requiring it to be on before a page is loaded is reasonable. I presume the caching happens at the page level though, so if I enable the pref, and then navigate the page (either through an address bar navigation or a link click) the new page will work as intended, right? Adding Arthur for visibility. How does this interact with things that survive page loads? *Workers (Shared/Background whatever other types of Workers there are...)
Flags: needinfo?(tom) → needinfo?(arthuredelstein)
Comment 42•7 years ago
|
||
I agree that it is reasonable to make sure the parameter is switched on *before* the page is loaded. I changed the steps and the results are as expected now. Here are the updated steps and results: Verification steps: 1. Set parameter privacy.resistFingerprinting to true 2. Open a new tab, and navigate to http://cnn.com 3. Open Console, and type the following commands 3a. performance.timing 3b. performance.getEntriesByType('resource').filter(item => item.name.includes("index.html")) 3c. window.performance.getEntries() 3d. performance.getEntries({name : "Begin", entryType: "mark"}) 3e. performance.getEntriesByType("mark") 3f. performance.getEntriesByName("domReady") 3g. performance.mark("mySetTimeout-start"); setTimeout(function() { performance.mark("mySetTimeout-end"); performance.measure( "mySetTimeout", "mySetTimeout-start", "mySetTimeout-end" ); var measures = performance.getEntriesByName("mySetTimeout"); var measure = measures[0]; console.log("setTimeout milliseconds:", measure.duration) performance.clearMarks(); performance.clearMeasures(); }, 1000); Expected results: All the output should be either zero, or empty Actual results: Same as expected results I will let Tim and Arthur answer the other questions from Tom Ritter.
Comment 43•7 years ago
|
||
(In reply to Tom Ritter [:tjr] from comment #41) > How does this interact with things that survive page loads? *Workers > (Shared/Background whatever other types of Workers there are...) For the record. We discussed this issue in a meeting. The conclusion: We are still concerned about caching in the event of background workers and other things that survive page loads. We will file a new bug to track it.
Flags: needinfo?(ettseng)
Flags: needinfo?(arthuredelstein)
Comment 44•7 years ago
|
||
(In reply to Tom Grabowski [:TomGrab] from comment #42) > I agree that it is reasonable to make sure the parameter is switched on > *before* the page is loaded. I changed the steps and the results are as > expected now. > Expected results: > All the output should be either zero, or empty > > Actual results: > Same as expected results Thanks, Tom! Then we can close this bug. :)
Status: REOPENED → RESOLVED
Closed: 7 years ago → 7 years ago
Resolution: --- → FIXED
Updated•7 years ago
|
Status: RESOLVED → VERIFIED
Updated•5 years ago
|
Component: DOM → DOM: Core & HTML
You need to log in
before you can comment on or make changes to this bug.
Description
•