Redirect Mouse Input to Attacker Controlled Position while Visible Cursor Remain on Original Position
Categories
(Firefox :: Security, defect)
Tracking
()
People
(Reporter: sourc7, Assigned: tnikkel)
References
(Regressed 1 open bug, Regression)
Details
(4 keywords, Whiteboard: [reporter-external] [client-bounty-form][adv-main103+][adv-esr91.12+][adv-esr102.1+])
Attachments
(13 files)
7.39 KB,
application/x-zip-compressed
|
Details | |
185.07 KB,
video/mp4
|
Details | |
319.91 KB,
video/mp4
|
Details | |
7.66 KB,
application/x-zip-compressed
|
Details | |
156.47 KB,
video/mp4
|
Details | |
4.36 KB,
application/zip
|
Details | |
168.23 KB,
video/mp4
|
Details | |
1.14 KB,
application/x-zip-compressed
|
Details | |
615.10 KB,
video/mp4
|
Details | |
6.92 KB,
text/plain
|
Details | |
48 bytes,
text/x-phabricator-request
|
dmeehan
:
approval-mozilla-beta+
dmeehan
:
approval-mozilla-esr102+
|
Details | Review |
48 bytes,
text/x-phabricator-request
|
dmeehan
:
approval-mozilla-esr91+
|
Details | Review |
201 bytes,
text/plain
|
Details |
After using overflow-block: hidden
combined with large transform: scale
surprisingly the mouse input will be redirected to another position (including on Toolbar, Permission panel). I found the redirect click position can be controlled through scale
number to click "Allow" on the permission panel while the visible cursor position still on the HTML page.
As the testcase using scale
to redirect the mouse input, the mouse redirect position may different across OS (i.e. not hitting the permission panel), I have adjusted the scale number on the testcase to work (as on PoC video) on the following device (with Fission enabled):
Tested on:
- Firefox 95.0a1 (2021-10-25) on Arch Linux (X11) (2560x1440)
- Firefox 95.0a1 (2021-10-25) on Windows 10 (Laptop with 1920x1080 screen and VirtualBox VM with 2560x1440 guest screen)
Steps to reproduce:
- Extract attached launcher.zip
- Visit attached launcher-windows.bundle.html or launcher-kdex11.bundle.html
- Click "Launch" button
- Move cursor to "Download" image, the "Allow" button on permission panel will be highlighted
- While the "Allow" button highlighted
- Click the "Download" image
- Location permission is now allowed
Reporter | ||
Comment 1•3 years ago
|
||
Reporter | ||
Comment 2•3 years ago
|
||
Reporter | ||
Comment 3•3 years ago
|
||
It is also possible to redirect mouse input to "Add" WebExtension while cursor on "Download" image. The WebExtension install PoC is attached in launcher-webextension.zip.
Reporter | ||
Comment 4•3 years ago
|
||
Reporter | ||
Comment 5•3 years ago
|
||
Okay, it turns out the OS Display Scaling is the big factor, all above testcase is reproduced on OS scaling 125%, when I change the display scaling to 100% the entire behavior is different.
I've adjusted the scale
to be able to reproduce on OS scaling 100%, also tested works on same device above. I see after changing resolution on guest machine (auto-resize guest display) the testcase still works the same.
Reporter | ||
Comment 6•3 years ago
|
||
Updated•3 years ago
|
Comment 7•3 years ago
|
||
This is a totally different issue from bug 1737751. This is probably math errors in APZ with really big transforms causing mouse events to go outside the content area or such. Botond / Hiro, perhaps you know where stuff might be going wrong?
Comment 8•3 years ago
|
||
Though I can't reproduce this issue on my Linux box with 200% scaled display (I don't even see the download image), it looks an our webrender hit testing issue. If Botond is hard to take time on this, I will jump in.
One thing I don't yet quite understand is, the permission popup window is not apz-aware one, how we pick it. Even if APZ picked a wrong target, I assume it's the newly opened browser window, then the browser window chooses the popup? That's a plausible scenario I can think of.
I wonder whether this issue also happens with the old non webrender backend.
Comment 9•3 years ago
|
||
Oops, I forgot saying, I did CC Timothy, he might have some insights on this.
Assignee | ||
Comment 10•3 years ago
|
||
Fission is required for me to reproduce. Webrender is also required for me to reproduce (if I use nightly 2021-06-01 where I can disable webrender).
Regression from bug 1675547. I'm guessing there is a scroll frame we activate in the dialog so that apz can target it? Whereas before that change it was not active, so apz could not target it. So the bug was likely present before that bug, and could manifest if a dialog had an already active scroll frame in it.
Webrender still seems required though, if I turn on fission, webrender off, and activate all scroll frames for nonwr on then I can't reproduce.
Confirmed that flipping apz.wr.activate_all_scroll_frames_when_fission to false fixes the problem.
Confirmed that setting apz.wr.activate_all_scroll_frames to true allows me to reproduce when fission is disabled.
Updated•3 years ago
|
Comment 11•3 years ago
|
||
Set release status flags based on info from the regressing bug 1675547
Assignee | ||
Comment 12•3 years ago
|
||
The scrollframe that gets activated is the body of the page in the test case. And indeed I can reproduce the bug without fission if I do something to make that scrollframe active first.
We untransform the mouse coords before passing them to the root presshell in the parent process here
the transforms there are
transformToApzc
[7.8287222038397886e-08 0 0 0]
[0 7.8287222038397886e-08 0 0]
[0 0 1 0]
[883.99981689453125 74.155632019042969 0 1]
transformToGecko
[12773476 0 0 0]
[0 12773476 0 0]
[0 0 1 0]
[-11291751424 -947225216 0 1]
outTransform
[0.99999994039535522 0 0 0]
[0 0.99999994039535522 0 0]
[0 0 1 0]
[-1024 0 0 1]
So it's as if we have a 1024 pixel async scroll offset permanently. I haven't worked out in detail how we get these matrices but the large scales involved seem like they could generate these, with the -1024 coming about because of float inaccuracies?
When we build the display list for GetFrameForPoint to find the targeted frame I guess we walk into the placeholders for open menupopups (like we do for other out of flow content like fixed or abs pos) and so we can target things in the popup with an event that was sent to the main widget, and the root frame of it.
I haven't thought about how to fix this very much yet, but possible ideas so far:
- treat apzcs with scales too big or too small as if the transform is non-invertible, ie they are dead to events etc. We'd have to come up with some kind of assurance that the limits work to avoid this problem and also don't affect real content.
- do the required computations somehow to avoid the floating point inaccuracies. Is this always possible? Don't we eventually have to hit a limit?
- something else.
The old layers hit testing code did seem to manage to avoid this (although it might just be luck), so perhaps looking into that might be useful. It could also be a dead end as the webrender hit testing is quite different and necessarily (for fission) more precise.
Even if we fix this large/small scale issue wouldn't it be possible for a page to create a long-lasting async scroll offset to cause mouse events in the content area to target chrome? The page could for example ask for a smooth scroll and then immediately enter an infinite busy loop. Or the page could be designed in such a way that the user wants to scroll down the right amount while the page is already in an infinite busy loop.
Even outside of attacker scenarios, if there is an async scroll offset of 100 on a scrollable subframe, and the user clicks in the subframe, but within 100 pixels of the scrollport of the subframe, the click will get moved 100 pixels to be outside of the subframe scrollport. More generally, anytime that we untransform using the targeted apzc A1 but then when we dispatch the event and find the frame target T, and T is not a descendant of A1 we will send the event to the wrong place.
Reporter | ||
Comment 13•3 years ago
|
||
I can only reproduce the issue when WebRender is enabled, it turns out I also able to reproduce on Fission disabled.
By using overflow-y: hidden
combined with transform scale
or matrix
it also works to move the mouse coordinate.
When using mozregression with prefs gfx.webrender.enabled: true
then visit attached launcher-mozregression-20180502.zip testcase, I can reproduce the issue from FF build date 2018-05-02, after the popup launched, right-clicking the page will show the context menu away from the cursor position.
Reporter | ||
Comment 14•3 years ago
|
||
Updated•3 years ago
|
Assignee | ||
Comment 15•3 years ago
•
|
||
The first two matrices in comment 12 are actually inverses of each other, however the 883.99981689453125 in the first matrix can't be represented accurately enough by a float so that the -1024 doesn't show up in the product. It should be 883.999893529, note how it starts differing after 7 digits, ie float precision.
So that might lead to a solution: if the transform matrix of an apzc times it's inverse is too far from the identity then we don't allow it to produce a hit.
I looked at why layers isn't affected and I think it's just dumb luck: when testing if the apzc for the body element is a hit we determine that it is not (which is incorrect) and so we hit the html element and we avoid any big scales.
Attached the hit testing tree and hittest comparing layers and webrender.
Updated•3 years ago
|
Comment 16•3 years ago
|
||
Thanks Timothy for investigating!
(In reply to Timothy Nikkel (:tnikkel) from comment #15)
The first two matrices in comment 12 are actually inverses of each other, however the 883.99981689453125 in the first matrix can't be represented accurately enough by a float so that the -1024 doesn't show up in the product. It should be 883.999893529, note how it starts differing after 7 digits, ie float precision.
So that might lead to a solution: if the transform matrix of an apzc times it's inverse is too far from the identity then we don't allow it to produce a hit.
This approach sounds promising to me.
(In reply to Timothy Nikkel (:tnikkel) from comment #12)
Even if we fix this large/small scale issue wouldn't it be possible for a page to create a long-lasting async scroll offset to cause mouse events in the content area to target chrome? The page could for example ask for a smooth scroll and then immediately enter an infinite busy loop. Or the page could be designed in such a way that the user wants to scroll down the right amount while the page is already in an infinite busy loop.
Even outside of attacker scenarios, if there is an async scroll offset of 100 on a scrollable subframe, and the user clicks in the subframe, but within 100 pixels of the scrollport of the subframe, the click will get moved 100 pixels to be outside of the subframe scrollport. More generally, anytime that we untransform using the targeted apzc A1 but then when we dispatch the event and find the frame target T, and T is not a descendant of A1 we will send the event to the wrong place.
My understanding is that FlushRepaintsToClearScreenToGeckoTransform(), which is called when receiving a mouse-down among other scenarios, is intended to address this issue in the case where it arises from an actual async transform (rather than an inaccuracy introduced by multiplying a CSS transform by its inverse).
Comment 17•3 years ago
|
||
Set release status flags based on info from the regressing bug 1675547
Updated•3 years ago
|
Updated•3 years ago
|
Updated•3 years ago
|
Assignee | ||
Comment 18•3 years ago
|
||
Updated•3 years ago
|
Assignee | ||
Comment 19•3 years ago
|
||
(In reply to Timothy Nikkel (:tnikkel) from comment #12)
When we build the display list for GetFrameForPoint to find the targeted frame I guess we walk into the placeholders for open menupopups (like we do for other out of flow content like fixed or abs pos) and so we can target things in the popup with an event that was sent to the main widget, and the root frame of it.
Just wanted to clarify this point (if not for anyone else at least for myself). We don't walk into popup out of flows when building a display list for hit testing.
In PresShell::EventHandler::ComputeRootFrameToHandleEvent we call ComputeRootFrameToHandleEventWithPopup
which eventually iterates the list of open popups
to see if one of them is where the event should be handled.
![]() |
||
Comment 20•3 years ago
|
||
Backed out for causing build bustages in WRHitTester.cpp:
https://hg.mozilla.org/integration/autoland/rev/3a0817ff4dc34ecc5495b0556295c768fa8f4f73
Push with failures: https://treeherder.mozilla.org/jobs?repo=autoland&group_state=expanded&resultStatus=retry%2Ctestfailed%2Cbusted%2Cexception%2Cusercancel&revision=121326268074712ac379a9a6a9308e08ce110e1f
Failure log: https://treeherder.mozilla.org/logviewer?job_id=383003066&repo=autoland
gfx/layers/apz/src/WRHitTester.cpp:154:66: error: too few arguments to function call, expected 2, have 1
Assignee | ||
Updated•3 years ago
|
![]() |
||
Comment 21•3 years ago
|
||
r=botond
https://hg.mozilla.org/integration/autoland/rev/7e14d6a790b288a98eb4a9190e9b737e9e7f01e2
https://hg.mozilla.org/mozilla-central/rev/7e14d6a790b2
Updated•3 years ago
|
Comment 22•3 years ago
|
||
Is this ready for uplift requests? Note that ESR91 will need a bit of rebasing due to bug 1729118.
Assignee | ||
Comment 23•3 years ago
|
||
Comment on attachment 9275430 [details]
Bug 1737722. r?botond
Beta/Release Uplift Approval Request
- User impact if declined: attacker could user move mouse input
- Is this code covered by automated tests?: No
- Has the fix been verified in Nightly?: Yes
- Needs manual test from QE?: No
- If yes, steps to reproduce:
- List of other uplifts needed: None
- Risk to taking this patch: Low
- Why is the change risky/not risky? (and alternatives if risky): patch only has an effect with huge transforms that real content should never hit
- String changes made/needed:
- Is Android affected?: No
ESR Uplift Approval Request
- If this is not a sec:{high,crit} bug, please state case for ESR consideration: sec mod, low risk
- User impact if declined: attacker could user move mouse input
- Fix Landed on Version: 104
- Risk to taking this patch: Low
- Why is the change risky/not risky? (and alternatives if risky): patch only has an effect with huge transforms that real content should never hit
Assignee | ||
Comment 24•3 years ago
|
||
Updated•3 years ago
|
Comment 25•3 years ago
|
||
A patch has been attached on this bug, which was already closed. Filing a separate bug will ensure better tracking. If this was not by mistake and further action is needed, please alert the appropriate party.
Comment 26•3 years ago
|
||
Comment on attachment 9275430 [details]
Bug 1737722. r?botond
Approved for 103.0 RC1 and ESR102.1, thanks.
Comment 27•3 years ago
|
||
uplift |
Comment 28•3 years ago
|
||
uplift |
Updated•3 years ago
|
Assignee | ||
Comment 29•3 years ago
|
||
Comment on attachment 9285574 [details]
Bug 1737722. esr91. r?botond
ESR Uplift Approval Request
- If this is not a sec:{high,crit} bug, please state case for ESR consideration: sec mod, low risk
- User impact if declined: attacker could user move mouse input
- Fix Landed on Version: 104
- Risk to taking this patch: Low
- Why is the change risky/not risky? (and alternatives if risky): patch only has an effect with huge transforms that real content should never hit
Updated•3 years ago
|
Updated•3 years ago
|
Comment 30•3 years ago
|
||
Comment on attachment 9285574 [details]
Bug 1737722. esr91. r?botond
Approved for ESR91.12, thanks.
Comment 31•3 years ago
|
||
uplift |
Comment 32•3 years ago
|
||
Hi Irvan! Can you please help us verifying this bug on the fixed builds?
Unfortunately, I am not able to reproduce the issue even though I've tried with the test cases from comment 0 and comment 13. I had fission enabled as well as webreneder on an affected Nightly build (2021-10-15), but the "Download" image was not displayed on my Win 10 x64 machine.
Updated•3 years ago
|
Updated•3 years ago
|
Reporter | ||
Comment 33•3 years ago
|
||
(In reply to Ciprian Georgiu [:ciprian_georgiu], Release Desktop QA from comment #32)
Hi Irvan! Can you please help us verifying this bug on the fixed builds?
Unfortunately, I am not able to reproduce the issue even though I've tried with the test cases from comment 0 and comment 13. I had fission enabled as well as webreneder on an affected Nightly build (2021-10-15), but the "Download" image was not displayed on my Win 10 x64 machine.
Alright, I'm currently checking this now.
Comment 34•3 years ago
|
||
Reporter | ||
Comment 35•3 years ago
|
||
(In reply to Ciprian Georgiu [:ciprian_georgiu], Release Desktop QA from comment #32)
Hi Irvan! Can you please help us verifying this bug on the fixed builds?
Unfortunately, I am not able to reproduce the issue even though I've tried with the test cases from comment 0 and comment 13. I had fission enabled as well as webreneder on an affected Nightly build (2021-10-15), but the "Download" image was not displayed on my Win 10 x64 machine.
On Windows 11 the "Download" image is disappear after Bug 1757647 - Implement Windows 11 overlay scrollbars is applied, to make "Download" image re-appear we can toggle widget.windows.overlay-scrollbars.enabled
from true
to false
.
On Linux the "Download" image is disappear after scrollbar is refactored on pushlog https://hg.mozilla.org/integration/autoland/pushloghtml?fromchange=d02c31423ae04546ab8dd3c2fa107a03fb66b629&tochange=ef94ce8ed301e54b5df8b578d7f1d5bdfead2c0d, unfortunately there are no prefs switch to undo the patch, but we can also test by right click into the page, after single tap to the page then right click the context menu will appear on different location if it still reproducible.
When verifying the bug on Windows 11 with resolution 1920x1080 on 125% scale using testcase on comment 0, I verified it has been fixed on following build:
- Firefox 104.0a1 (2022-07-19) (64-bit)
- Firefox 103.0 (64-bit)
- Firefox 102.1.0esr (64-bit)
- Firefox 91.12.0esr (64-bit) (
webrender.enabled
totrue
)
I also verified the bug is no longer reproducible on Linux platform using Firefox Nightly 104.0a1 (2022-07-19) (64-bit) by right click into the page.
The Firefox ESR102.1 download link that you refer is point to Firefox ESR102.0.1 version released on 11-Jul-2022 which still reproducible. I think it's typo which has to refer to ESR102.1.0 link which is fixed on that build.
Updated•3 years ago
|
Comment 36•3 years ago
|
||
Thank you very much, Irvan!
(In reply to Irvan Kurniawan (:sourc7) from comment #35)
The Firefox ESR102.1 download link that you refer is point to Firefox ESR102.0.1 version released on 11-Jul-2022 which still reproducible. I think it's typo which has to refer to ESR102.1.0 link which is fixed on that build.
Indeed, I wanted to point out the download link from ESR102.1.
Updated•3 years ago
|
Updated•3 years ago
|
Updated•2 years ago
|
Updated•9 months ago
|
Description
•