Navigating to another page does not reset silent lock state
Reported by
xis...@gmail.com,
May 22 2017
|
||||||||||||
Issue descriptionVULNERABILITY DETAILS When the users click the button using requestPointerLock() API, the browser pops up the message prompt "press esc to show your cursor". But the PointerLock prompt message can be hidden. VERSION Chrome Version: 58.0.3029.110+[Stable], 60.0.3100.0+[Canary] Operating System: [Windows/MAC] REPRODUCTION CASE lock.html works on http(s):// or file:// (1)Click button "pointerlock" (2)Click button "pointerlock1"
,
May 23 2017
I think the pop-up prompt message should have the orgin from the lock.html URL shown. Such as "evil.com - press esc to show your cursor" http://example.com/1.html ===1.html=== <iframe src="http://www.evil.com/lock.html"></iframe> ===1.html===
,
May 23 2017
#2: Not sure how that's relevant (since the bug is the popup doesn't show at all). We decided to remove the origin from the prompt in 2015 since it doesn't help you make an informed decision about whether to stay in pointer lock (since there is no privacy issue, just the annoyance of not having access to your cursor, so it doesn't make a difference whether an iframe took the lock or the outer frame). Confirmed the original issue. I was also able to dig down and realise that it's the location.replace (or location.assign) that causes this. It doesn't actually have to be empty quotes -- you can do any navigation and the pointer lock message will not show after the navigation. I've modified the example to do the attack across two pages. To repro using my files: 1. Load lock.html (file:// works). 2. Click "pointerlock". It navigates to lock1.html. 3. Click "pointerlock1".
,
May 23 2017
Investigation of the code flow for the second button click (on the second page): - ExclusiveAccessManager::GetExclusiveAccessExitBubbleType is returning NONE on that second page. - This is because MouseLockController::IsMouseLockedSilently() is returning true. - This is because MouseLockController::RequestToLockMouse() is being called with last_unlocked_by_target=true. - This can be traced all the way back to the renderer: MouseLockDispatcher keeps an instance variable |unlocked_by_target_| that tracks whether the lock has been voluntarily released, and sends it to the browser in an IPC message which ends up being passed as |last_unlocked_by_target| to MouseLockController::RequestToLockMouse ( Issue 725365 ). - MouseLockDispatcher has global lifetime (per renderer), and its state persists across navigations if they are on the same renderer. - MouseLockDispatcher is owned by RenderWidget, which has the same lifetime. The fix is we need to have the RenderWidget delete and recreate the MouseLockDispatcher on navigation.
,
May 23 2017
,
May 23 2017
It turns out this is really hard (maybe impossible without refactoring) because RenderWidget knows nothing about navigation. The Mojo team is trying to get rid of it apparently. :(
,
May 23 2017
,
May 23 2017
,
May 23 2017
,
May 23 2017
re #6: It's not strictly true that RenderWidget knows *nothing* about navigation. When a non-same-page navigation commits, RenderFrameImpl calls RenderWidget::IncrementContentSourceId() which effectively tells the RenderWidget that a navigation has occurred (ContentSourceId is used in the browser process to link compositor frames to page loads). Would it work to generalize that method a bit, so that in addition to incrementing the ContentSourceId, it also re-created the MouseLockDispatcher? I haven't looked that closely at mouse lock, but sometimes the catch on things like that is if there is browser side state that can get out of sync.
,
May 23 2017
Pointer lock is not a security or privacy threat. Pointer lock is a UX issue. Data can not be revealed, distributed, etc. This was established in 2011 and occasionally needs to be recirculated. I've brought this up on relevant email thread, will give that time to be addressed, and then clear the security flags from these issues.
,
May 24 2017
https://www.w3.org/TR/pointerlock/#security ========== Security Concerns: 1. User actions may be misdirected to elements the user did not intend to interact with. 2. Pointer Lock will remove the ability of a user to interact with user agent and operating system controls 3. Pointer Lock can be called repeated by script after user exits pointer lock, blocking user from meaningful progress. 4. Full screen exit instructions are displayed in some user agents when the pointer is moved to the top of the screen. During pointer lock that gesture is not possible. Responses: 1. User agents may limit what security origins may lock the pointer. 2. User agents may prompt for confirmation before locking, this preference may be saved as a content setting. 3. Escape will always be provided by a default unlock gesture, e.g. Esc key. 4. Persistent display of escape instructions can be provided. 5. Repeated escapes of pointer lock can signal user agent to not re-lock the pointer without more specific engagement gesture, e.g. similar to how Chrome 6. suppresses repeated alert() calls. 7. Changing to new tabs, windows, or any other action that causes a page to lose focus will exit pointer lock. Pointer lock can only be engaged when the window is in focus in the user agent and operating system. Recommendations: 1. Esc key should exit pointer lock. 2. Preferences per sub-domain can be used to allow or block pointer lock, similar to pop-up, geolocation, and fullscreen. Pointer lock is a required user interaction mode for certain application types, but carries a usability concern if maliciously used. An attacker could remove the ability for a user to control their mouse cursor on their system. User agents will prevent this by always providing a mechanism to exit pointer lock, by informing the user of how, and by limiting how pointer lock can be entered. User agents will determine their own appropriate policies, which may be specialized per device or differ based on user options.
,
May 24 2017
#10: Ah great, I looked for a method that might've been called on navigation but didn't find that. In that case, I think we can have it recreate the MouseLockDispatcher. (It would also be valid to simply add a method on MouseLockDispatcher that's called on navigation which resets its state.)
,
May 24 2017
#13: I found another Bug Issue 526378 --‘Pointerlock browser UI hijack’. I think this bug can be reproduced. lock2.html works on http(s):// or file://. Open and click.
,
May 24 2017
#14 that bug was marked fixed a long time ago. If you think it's still broken, it's a separate issue to that, so please open a new bug.
,
May 24 2017
#15: OK, I'm going to submit a new bug now.
,
May 24 2017
,
May 25 2017
According to #10 RenderWidget has information about navigation. The plan is to move the silent flag to RenderWidgetHost, and reset the flag on navigation.
,
May 26 2017
Clearing security flags. Unexpected mouse lock can be a user annoyance, and this can be considered a denial of service bug, but since that is the extent of exposure we don't consider it a security vulnerability. https://dev.chromium.org/Home/chromium-security/security-faq#TOC-Are-denial-of-service-issues-considered-security-bugs-
,
Sep 14 2017
The fix for issue 725370 ensures that the exit instruction bubble will be displayed for a certain amount of time before granting silent mouse lock permission to current WebContent. Demos in #0, #3, #14 won't cause issues anymore as the exit instruction bubble will be displayed to user properly. Removing 'Security: ' from title to avoid confusion according to #19. Lowering priority as the impact has been reduced, and keep bug open since we still want to clear the permission bit on navigation. (Un-assigning myself so others can pick up)
,
Jan 9 2018
,
Jan 10
This issue has been Available for over a year. If it's no longer important or seems unlikely to be fixed, please consider closing it out. If it is important, please re-triage the issue. Sorry for the inconvenience if the bug really should have been left as Available. For more details visit https://www.chromium.org/issue-tracking/autotriage - Your friendly Sheriffbot
,
Jan 10
Can still repro, specially the demo in #c3. As per #c4, looks like resetting RenderWidgetMouseLockDispatcher on navigation should fix the remaining problem: https://cs.chromium.org/chromium/src/content/renderer/render_widget.h?rcl=f335422d89988a17a8b2d4ecd1781ca206c1fe87&l=952 |
||||||||||||
►
Sign in to add a comment |
||||||||||||
Comment 1 by wfh@chromium.org
, May 22 2017Labels: Security_Severity-Medium Security_Impact-Stable OS-All Pri-2
Owner: mgiuca@chromium.org
Status: Assigned (was: Unconfirmed)