Closed Bug 1445844 (CVE-2019-11695) Opened 2 years ago Closed 1 year ago

Custom cursor goes outside the bounds of the web content in "malware" website

Categories

(Core :: Layout, defect, P3)

58 Branch
defect

Tracking

()

VERIFIED FIXED
mozilla67
Tracking Status
firefox67 --- verified

People

(Reporter: bignis, Assigned: emilio)

References

(Blocks 2 open bugs)

Details

(4 keywords, Whiteboard: [adv-main67+])

Attachments

(5 files)

User Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:58.0) Gecko/20100101 Firefox/58.0
Build ID: 20180206200532

Steps to reproduce:

1) Navigate to https://twomastersmedia.com/iops/?c5aa9d589430490ftfn1d5aa9d58943083=(888)%20498-4480# (note this is a website that tries to capture all events, so it's hard to get out of it)
2) Move the cursor around in the area with the red background
3) Move the cursor to the Firefox's top bar buttons (Home button / Hamburger Menu, etc) or Address bar.  Click the mouse.

Special note: keep slowly moving the mouse cursor upward toward the top of the screen, it will "go off the top" and then appear again slightly below the top bar.  That's the "real cursor" and all clicks are registered by that.


Actual results:

Nothing happens, it appears the click is not registered.  Note that if you click and drag downward a bit, it highlights some text on the webpage itself!


Expected results:

The click should have been received by Firefox.

Note: it appears to be caused by a fake cursor - shouldn't Firefox prevent that somehow?
Hi bignis,

I cannot access the link from the bug description (Status code: 404 Not Found), Step 1). Can you please check it or send me a link that I can access to reproduce the issue?
Flags: needinfo?(bignis)
hmmmmm, I can still access the website.  Attached is a cURL response from it when I used:

curl "https://twomastersmedia.com/iops/?c5ab1b305c23f50ftfn1d5ab1b305c242e=(888)"%"20498-4480#" -H "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" --compressed -H "Accept-Language: en-US,en;q=0.5" -H "Cache-Control: max-age=0" -H "Connection: keep-alive" -H "Cookie: redirect=1" -H "DNT: 1" -H "Host: twomastersmedia.com" -H "Upgrade-Insecure-Requests: 1" -H "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:59.0) Gecko/20100101 Firefox/59.0"

here's a cURL HEAD request for just the headers in case it helps:

curl "https://twomastersmedia.com/iops/?c5ab1b305c23f50ftfn1d5ab1b305c242e=(888)"%"20498-4480#" -H "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" --compressed -H "Accept-Language: en-US,en;q=0.5" -H "Cache-Control: max-age=0" -H "Connection: keep-alive" -H "Cookie: redirect=1" -H "DNT: 1" -H "Host: twomastersmedia.com" -H "Upgrade-Insecure-Requests: 1" -H "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:59.0) Gecko/20100101 Firefox/59.0" -X HEAD -I

HTTP/2 200
date: Wed, 21 Mar 2018 01:24:44 GMT
content-type: text/html; charset=UTF-8
server: nginx
p3p: CP='CAO DSP COR CUR ADM DEV TAI'
cache-control: private, max-age=0, no-cache, no-store
Flags: needinfo?(bignis)
In my opinion the behaviour is the malware site's fault and as far as I know Firefox has no special mechanism in place for this.
My advice would be to avoid entering malware sites.

Given the above, I'll close the issue es Invalid.
Status: UNCONFIRMED → RESOLVED
Closed: 2 years ago
Resolution: --- → INVALID
David, just to make sure I've expressed my view of the problem clearly - do we expect Firefox to allow a custom cursor to be drawn over-top of the Address Bar in Firefox?  Seems like a bad thing to me that the browser should disallow as it is being used by an evil website.

Yeah, obviously avoiding the website is a good thing to do.  The reason I filed this bug is because I believe it indicates a problem with the browser that this evil website is exploiting.
Flags: needinfo?(david.olah)
Hi Christoph, what do you think about this bug?
Flags: needinfo?(david.olah) → needinfo?(ckerschb)
(In reply to David Olah from comment #6)
> Hi Christoph, what do you think about this bug?

Dan might be in a better position to evaluate this bug. Dan, what do you think?
Flags: needinfo?(ckerschb) → needinfo?(dveditz)
This site is not blocked by SafeBrowsing. If we think it's a malicious site we should report it so it gets blocked.

I get a 404 so thanks for recording and attaching the page. We should not allow custom cursors to escape the content area, especially not above the "Line of Death" into the chrome toolbar area as this site does.

Firefox can't tell if a custom cursor is simply creative or if it's a "fake" (one that looks like the real cursor only offset). If the site is faking things inside their own web content that's one thing, but if that fake gets them to click (or not click) on actual browser chrome that can be a security issue.

Another problem with fake cursors is getting the user to click on permission prompts, typically these days "door hangers" that bleed over the web content area. We need to keep these custom cursors out of those areas as well (harder!). In this example the "fake" cursor is above the real pointer location; in an attempt to lure a prompt click the fake image would be below or to the side of the real (invisible) pointer location.

As used in this tech support scam example it's a "sec-low" spoof, but being able to spoof clicks onto permission prompts raises the stakes. In particular this could be used to get someone to install a malicious web extension or enable their camera and microphone.
Blocks: eviltraps
Status: RESOLVED → REOPENED
Component: Untriaged → Layout
Ever confirmed: true
Flags: needinfo?(dveditz)
Product: Firefox → Core
Resolution: INVALID → ---
Summary: Custom cursor goes outside the bounds of the browser window in "malware" website → Custom cursor goes outside the bounds of the web content in "malware" website
Really interesting that everyone but me gets a 404.  Makes me think the host is doing some kind of filtering to deny access to some.  Anyway, the evil website is still working fine for me right now, so attaching a .HAR file of the content just in case it's needed (captured via Firefox's Web Developer Network tool).
The way this works is that they use a cursor image that's 128x128 pixels, and shows the arrow in the top-right corner, with the actual hotspot for the cursor being somewhere else.

I'm not sure what we'd be able to do about this without breaking custom cursors entirely, besides limiting the size. I guess we could try to do more math on the layout size and remove the custom cursor if the cursor image starts overlapping the boundary of the content window? :dholbert, does that sound doable at all?
Flags: needinfo?(dholbert)
That sounds like a good approach, but I don't know enough about our cursor code to have an opinion on how doable it would be.
Flags: needinfo?(dholbert)
Priority: -- → P3
another example site which uses this to deliver malware: https://s3.amazonaws.com/gresrs/uk/index.html

warning: malware.
Possibly related bug #1450083
Duplicate of this bug: 1450083
> I'm not sure what we'd be able to do about this without breaking custom cursors entirely

Could we not bound the cursor by its visible region? We cant just ban transparency but does seem like cropping out any large area of transparency / making sure the area the mouse is actually clicking has something visible would prevent this
(In reply to Dale Harvey (:daleharvey) from comment #16)
> > I'm not sure what we'd be able to do about this without breaking custom cursors entirely
> 
> Could we not bound the cursor by its visible region? We cant just ban
> transparency but does seem like cropping out any large area of transparency
> / making sure the area the mouse is actually clicking has something visible
> would prevent this

Well, as noted in earlier comments, the simplest way of fixing this is to just stop using the custom cursor when it overlaps with the chrome, even if the hotspot doesn't (yet). This wouldn't really affect "benign" custom cursors. The question is who knows our custom cursor code and whether that fix is feasible - if not, perhaps we could do what you're suggesting... Looks like Neil did the e10s support and Emilio did some pointer lock work. Maybe they can help.
Flags: needinfo?(enndeakin)
Flags: needinfo?(emilio)
Attached file cursor.html
I haven't done much cursor stuff actually, but I know some of the cursor bits. So what this is doing if I understand correctly is using a big cursor so that when the pointer is over content it seems it is over the chrome, right?

So this should be an adequate test-case.
So, I think the place to fix this is around the widget code (nsIWidget::SetCursor). There we can check the bounds of the widget and the image, along with the hotspot, and just fall back to the default cursor or something.

That's slightly annoying though, since the user could be hovering something that would usually have a pointer cursor or what not, and we wouldn't be able to fall back to it... Could we maybe clip the cursor to the widget instead during painting? I don't know. Looks like dbaron and smaug also have written / reviewed a bunch of the custom cursor stuff, so they may have opinions.
Flags: needinfo?(emilio)
Flags: needinfo?(enndeakin)
Duplicate of this bug: 1518189

I'm taking a look at this, will start with some preliminar refactoring.

Assignee: nobody → emilio
Depends on: 1520154
Depends on: 1520502

Do folks have opinions on the different approaches here? Chrome has a tentative plan that we like here https://bugs.chromium.org/p/chromium/issues/detail?id=880863#c41 (comment 41), but it's best if we can align on a solution.

(In reply to csharrison from comment #22)

Do folks have opinions on the different approaches here? Chrome has a tentative plan that we like here https://bugs.chromium.org/p/chromium/issues/detail?id=880863#c41 (comment 41), but it's best if we can align on a solution.

I think clipping the cursor is not great because the majority of the cursor may actually be transparent, and clipping the non-transparent area leaves the user without any kind of feedback...

I did a bunch of refactoring in bug 1520502 to be able to show the right cursor when intersecting the browser chrome, though I'm of course open to implementing something else :)

And for now, start blocking custom cursors that are larger than 64 pixels.

I wish I knew how to add a test for this, but I tested manually using the
test-case from bug 1518189 with and without hidpi.

We always treat the cursor image size as CSS pixels (and upscale it to device
pixels in HiDPI). We have bugs to stop doing that though (bug 1425694).

Pushed by ealvarez@mozilla.com:
https://hg.mozilla.org/integration/autoland/rev/d5850db1fb0d
Add a pref to block large custom cursors outside of the viewport's bounds. r=smaug
Status: REOPENED → RESOLVED
Closed: 2 years ago1 year ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla67
Duplicate of this bug: 1525898

Hey Emilio, sorry I missed this. In the Blink intent-to-deprecate I was planning on blocking custom cursors >32x32, but I now see you've done this only for >64x64 cursors.

Our usage data in Chrome 74 shows ~.01% of page visits impacted by the 32x32 scoping (i.e. only those pages have the cursors go outside of the viewport boundary). What do you think about making this more strict?

(In reply to csharrison from comment #28)

Hey Emilio, sorry I missed this. In the Blink intent-to-deprecate I was planning on blocking custom cursors >32x32, but I now see you've done this only for >64x64 cursors.

Our usage data in Chrome 74 shows ~.01% of page visits impacted by the 32x32 scoping (i.e. only those pages have the cursors go outside of the viewport boundary). What do you think about making this more strict?

+ni to radar this.

Flags: needinfo?(emilio)

I'm ambivalent, it seems ok to do that. It's a one-liner patch1.

I'm curious which kind of attacks can you do with cursors smaller than 64px though...

Flags: needinfo?(emilio)

It's not much, but at least in Chrome you can just barely get to the "x" button on a tab with 63px if the bookmark bar is hidden, and you can easily reach the extension buttons / back / forward / etc. If the limit is 32x, you can barely reach even those controls.

My slight preference is to protect more and revert to gating on >64x64 if we find compat issues.

I'm OK with erring on the side of caution and going with 32x so we have alignment. (Looks like we would based on this commit: https://chromium.googlesource.com/chromium/src/+/0acc6c91a8bce9237aa8c3a5085945339f50e150.)

I don't think we will want to ship Fx67 with the 64x limit and Fx68 with the 32x limit, however, so I guess we either get the change in during this week's soft freeze or do an uplift.

(In reply to Sean Voisen (:svoisen) from comment #32)

I'm OK with erring on the side of caution and going with 32x so we have alignment. (Looks like we would based on this commit: https://chromium.googlesource.com/chromium/src/+/0acc6c91a8bce9237aa8c3a5085945339f50e150.)

I don't think we will want to ship Fx67 with the 64x limit and Fx68 with the 32x limit, however, so I guess we either get the change in during this week's soft freeze or do an uplift.

I disagree with that, that chromium patch only adds a deprecation message, as far as I understand, so we'd be the only ones actually blocking the cursor.

Blocking 32px cursors adds significantly more risk. I'm fine landing that change on nightly, but probably not on 67... wdyt?

Flags: needinfo?(svoisen)
Depends on: 1534761
Blocks: 1534761
No longer depends on: 1534761

Filed bug 1534761 for that change.

Flags: needinfo?(svoisen)

Probably needs a docs mention

Keywords: dev-doc-needed
Blocks: 1534914

Is there any plan to do something more thorough here, or is this fix as far as it will go?

(In reply to Eric Shepherd [:sheppy] from comment #37)

Is there any plan to do something more thorough here, or is this fix as far as it will go?

Can you elaborate? I don't think there's any plan to add any more restrictions.

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

(In reply to Eric Shepherd [:sheppy] from comment #37)

Is there any plan to do something more thorough here, or is this fix as far as it will go?

Can you elaborate? I don't think there's any plan to add any more restrictions.

+ni to radar to :sheppy.

Flags: needinfo?(eshepherd)

This issue is not 100% fixed with doorhanger notifications.
I just tried it with the latest nightly (Build ID 20190322101035): https://i.imgur.com/4aQeyBz.mp4
(The cursor does not really flash like in the video, that's from the recording software.)

As you can see the custom cursor goes many pixels into the doorhanger.

This is from the following malicious website (still live):
hxxps://s3.us-east-2.amazonaws.com/rsscfr/de/index.html
(malicious XPI here: hxxp://s3.us-east-2.amazonaws.com/exyyt/de.xpi)

Flags: needinfo?(emilio)

Can you file a separate bug for that?

That's a quite different situation, and the fix for that would be fairly different (and probably way more complicated).

Note that the content process has no idea of whether there's a door-hanger around and what's its geometry. Also, how doorhangers and fullscreen interact in that site seems unfortunate...

Flags: needinfo?(emilio)

Filed bug 1538402.

Blocks: 1538402
Flags: qe-verify+

FYI, similar nonsense going on at https://s3.us-east-2.amazonaws.com/usgvgv/us/index.html

HAR capture attached

reported to Amazon

Sorry for adding the link, I tried to defang with \ but apparently Bugzilla just ignored the escapes.

Note to MDN writers:

I've added a note about this to the Fx67 rel notes:
https://developer.mozilla.org/en-US/docs/Mozilla/Firefox/Releases/67#CSS

In terms of other work, I think it makes sense to add a note about Fx/Chrome's change to the BCD for the cursor property?

Whiteboard: [adv-main67+]

What I meant earlier about "do we plan to do something more thorough" is this: the idea of just limiting the cursor size to a specific pixel maximum feels placeholder-ish to me, for a couple of reasons:

  • 32-pixel cursors are not very large; many games use larger cursors than this for various features, for example, and that feels very much like a serious restriction.

  • Using a pixel count maximum is especially problematic in a HiDPI or UltraDPI setting. a 32x32 pixel cursor on an extremely high resolution device is tiny.

  • It's just... not a very clean solution.

It seems like we could do some actual checking into the cursor image itself. Look at the cursor and look for things such as, perhaps:

  • Is the hotspot on a visible pixel which is part of a group of N[1] visible pixels, or within a small number of pixels of such a group? If not, is there a grouping of at least N visible pixels in every direction from the hotspot? This will prevent the hotspot from being off in a total void.

  • Along every edge of the cursor, there should be at least N pixels in a group that contacts the edge. There's no reason a cursor should have empty space on any side.

  • It might even make sense to crop images so that every edge has a grouping of N pixels making contact with each edge of the image.

[1] N is a computed number of pixels that, grouped together, are reasonably easily visible to the average person given the current display resolution.

Flags: needinfo?(eshepherd)

Documentation updated:

  • Submitted BCD PR 4111 to update data for Firefox and Firefox Android (which doesn't support cursor at all)
  • Added a paragraph to CSS cursor property page that says that browsers may choose to set a size limit

That should cover it (once the PR is merged and the production site updated).

I've managed to reproduce this issue on an affected Firefox 61.0a1 (2018-03-14) using Windows 10x64 by following the STR from comment 0.
This issue is verified fixed using Firefox 67.0b19 and Firefox 68.0a1(2019-05-12) on the following OSes: Windows 10x64, mac OS 10.14, Ubuntu 18.04x64 and Windows 7x64.
The top bar of Firefox is working fine except the part with the fake cursor on the page.

Status: RESOLVED → VERIFIED
Flags: qe-verify+
Alias: CVE-2019-11695

FYSA, encountered this again on http[:]//errorcode21210.mac-us209[.]live (TorBrowser 60.8.0) , javascript disabled.

I have HAR capture available if necessary.

The page also causes a denial-of-service condition in the latest FF 68.0.2 (bug 1575952)

Regressions: 1590191
No longer regressions: 1590191
You need to log in before you can comment on or make changes to this bug.