Closed Bug 1506842 Opened 3 years ago Closed 1 year ago

History Sniffing Timing Attack

Categories

(Core :: Layout, defect, P1)

defect

Tracking

()

RESOLVED FIXED

People

(Reporter: ronmasas, Assigned: emilio)

References

()

Details

(Keywords: csectype-disclosure, sec-moderate, Whiteboard: [reporter-external] [client-bounty-form] [verif?][pixel-stealing][layout:backlog])

Attachments

(2 files)

Attached file firefox-poc.html
I found that by generating thousands of CSS rules linked to the hyperlink “:visited” CSS condition it’s possible to detect the “visited” state of a given hyperlink tag by looking for delays in the page estimated frame rate.


VERSION
FireFox Quantum Version: 63.0.1 (64-bit)
Operating System: macOS Mojave 10.14.1, MacBook Pro (15-inch, 2017), 2.9 GHz Intel Core i7, 16 GB 2133 MHz LPDDR3

REPRODUCTION CASE
1. Open FireFox and visit https://www.google.com/
2. Open my POC page https://eix.co.il/firefox-history-leak/
3. Enter https://www.google.com/ to the search input and click on the check button - you should now see a spike.
Flags: sec-bounty?
dbaron: is this different than some of the "retail" (slow-ish) :visited attacks we already knew about?
Group: firefox-core-security → layout-core-security
Status: UNCONFIRMED → NEW
Component: Security → Layout
Ever confirmed: true
Flags: needinfo?(dbaron)
Product: Firefox → Core
I don't think this brings anything new to what we already know.
It is well known that painting to a canvas can be used as a timing channel.
Using requestAnimationFrame is an already known technique.
(Both of which are mentioned in the paper below.)

Fwiw, this got attention recently by https://motherboard.vice.com/en_us/article/zm9jd4/old-school-sniffing-attacks-can-still-reveal-your-browsing-history which surfaced on Slashdot and other places.
Based on the paper: https://www.spinda.net/papers/smith-2018-revisited.pdf
"With this strategy, actors can test 60 sensitive URLs per second."
Flags: needinfo?(dbaron)
Hi, unlike in the paper I don't use canvas / SVG filters / text-shadow etc - I generate thousands of unique CSS rules affected by the :visited condition.
With that said, I'm not sure if that affects the way you were planning to mitigate that.
Well, the attached PoC is using CanvasJS.Chart and chart.render() in 
a setInterval callback so it looks like it's using a <canvas> element...

Anyway, it doesn't change my assessment or our plans for fixing this problem.
Depends on: 1239897
Priority: -- → P3
Whiteboard: [reporter-external] [client-bounty-form] [verif?] → [reporter-external] [client-bounty-form] [verif?][pixel-stealing]
I can see how this might be confusing ;)
I only used it for visualization purposes.

Thank you all for taking a look
Ron

The bounty committee determined that this was too similar to known bugs describing abuses of :visited painting timing to qualify for a bounty.

Flags: sec-bounty? → sec-bounty-

We should try to mitigate these somehow. What WebKit did is pretty smart (https://trac.webkit.org/projects/webkit/changeset/244642), though our :visited architecture looks very different from that.

(In particular, in Gecko history queries are asynchronous, and in WebKit they are not).

Though actually, come think of it, I can think of something that may work and may not be too terrible to implement. In particular, we could allow at most one history query per link, and always repaint regardless of whether it's visited or not...

That last bit may be a bit perf sensitive, I'll put it behind a pref to test it first.

Assignee: nobody → emilio
Flags: needinfo?(emilio)
Depends on: 1590816
Depends on: 1591717

So that it is not time-able whether it is or isn't visited.

Blocks: 1224397

(In reply to Emilio Cobos Álvarez (:emilio) from comment #8)

That last bit may be a bit perf sensitive, I'll put it behind a pref to test it first.

I think we tried something like that a decade ago, and it was a pretty substantial performance regression then.

(In reply to David Baron :dbaron: 🏴󠁵󠁳󠁣󠁡󠁿 ⌚UTC-7 from comment #10)

I think we tried something like that a decade ago, and it was a pretty substantial performance regression then.

Do you have references? I'm confused since this required a fair amount of history service wrangling, so it may not be doing the same...

Flags: needinfo?(emilio)

Ah, found bug 557579.

So the perf regression seems decent (specially for pages like google.com and such). Daniel, would it be ok for you if I landed this code along with a disable-pref-by-default check, so I can do profiling on our regular nightly builds rather than locally?

Flags: needinfo?(dholbert)

That may be OK, but I'd like to punt to dbaron on that decision, if he's got cycles to think about this, since he's thought through this privacy leak more than I have (in bug 557579 as well as other bugs). Also, the cost/benefit decision around this feature's perhaps-inevitable perf cost may be something that he might need to make a final call on as module owner (depending on how sizeable the regression is), so we might as well involve him in the decision-making early. :)

(One reason I'm uneasy rubberstamping this: if we don't anticipate being able to pref this on without significant additional work, then landing this as a preffed-off feature could inadvertently point a bullseye on a problem that we're not in a position to be able to fix efficiently. Having said that: on the other hand, it would also give privacy-conscious users a way to opt-in to stronger protection, which is a silver lining to that bullseye-painting.)

Flags: needinfo?(dholbert) → needinfo?(dbaron)

(One reason I'm uneasy rubberstamping this: if we don't anticipate being able to pref this on without significant additional work, then landing this as a preffed-off feature could inadvertently point a bullseye on a problem that we're not in a position to be able to fix efficiently. Having said that: on the other hand, it would also give privacy-conscious users a way to opt-in to stronger protection, which is a silver lining to that bullseye-painting.)

I think we have a bunch of open bugs related to this issue. It's not a secret anymore these days, I'd think. We also have layout.css.visited_links_enabled for this too.

I want to experiment with better batching in the history service in order to deal with this better and hopefully mitigate/eliminate the perf regression.

Depends on: 1593690

Sorry for the delay...

Yeah, I'm ok with landing this; I think there's been enough discussion of this in public that having this code visible isn't going to be opening up anything new here.

Flags: needinfo?(dbaron)
Keywords: leave-open
Whiteboard: [reporter-external] [client-bounty-form] [verif?][pixel-stealing] → [reporter-external] [client-bounty-form] [verif?][pixel-stealing][layout:backlog]
Depends on: 1632765

Now that we triage by severity, setting priority to P1 to reflect backlog prioritization on this bug as either in-progress, or planned development in the near term. See https://wiki.mozilla.org/Platform/Layout#Backlog_Tracking_in_Bugzilla

Priority: P3 → P1

The leave-open keyword is there and there is no activity for 6 months.
:emilio, maybe it's time to close this bug?

Flags: needinfo?(emilio)

I think this should be fixed now. If this is still a problem let's file new issues.

Status: NEW → RESOLVED
Closed: 1 year ago
Flags: needinfo?(emilio)
Resolution: --- → FIXED
Group: layout-core-security → core-security-release
Duplicate of this bug: 557579
Group: core-security-release
You need to log in before you can comment on or make changes to this bug.