Closed Bug 1821886 (CVE-2023-37210) Opened 2 years ago Closed 1 years ago

Alerts break exiting non-DOM fullscreen leading to spoof using window prompt/alert

Categories

(Core :: DOM: Events, defect)

defect

Tracking

()

RESOLVED FIXED
115 Branch
Tracking Status
firefox-esr102 --- wontfix
firefox113 --- wontfix
firefox114 --- wontfix
firefox115 --- fixed

People

(Reporter: sas.kunz, Assigned: masayuki)

References

Details

(Keywords: csectype-spoof, reporter-external, sec-low, Whiteboard: [reporter-external] [client-bounty-form] [verif?][adv-main115+])

Attachments

(5 files)

i found vulnerabilty when using zoom feature using press Fn+F11 or F11 on keyboard , the web page can the webpage will go fullscreen,
and when it will exit fullscreen mode user must press Fn+F11 or F11 again. This will be used to spoof by using a window prompt / alert (do not exit fullscreen mode when pressing f11) so that the victim will think they have exited fullscreen mode

  1. open pocfullscreen.html
  2. press Fn+F11 or F11 on keyboard to using zoom feature (fullscreen)
    3 press Fn+F11 or F11 on keyboard again to exit zoom (fullscreen) (it show alert and not exit on fullscreen mode it can spoof )

mitigation:

  • when using zoom feature (fullscreen) show notification fullscreen
Flags: sec-bounty?
Attached file pocfullscreen.html
Attached image urlbar.jpg

new POC

  1. http://103.186.0.20/pocfullscreen.html
  2. press Fn+F11 or F11 on keyboard to using zoom feature (fullscreen)
    3 press Fn+F11 or F11 on keyboard again to exit zoom (fullscreen) (it show alert and not exit on fullscreen mode it can spoof )

Edgar, can you take a look? ISTM websites should not be able to prevent exiting F11-fullscreen.

Flags: needinfo?(echen)
Summary: using zoom feature (fullscreen) it can spoof using window prompt/alert → Alerts break exiting non-DOM fullscreen leading to spoof using window prompt/alert

Yes, website should not be able to prevent exiting fullscreen. It seems like alert() call in keydown event handler somehow suppress event handling for F11 to exit fullscreen. If you keep the alter open and press F11 again, fullscreen can be exited. I will check why alert() suppress fullscreen exit.

Parent process doesn't handle the eKeyPress (while receiving ReplyKey from content process) because it is preventDefaulted, https://searchfox.org/mozilla-central/rev/af78418c4b5f2c8721d1a06486cf4cf0b33e1e8d/dom/events/GlobalKeyListener.cpp#92-94. And it is preventDefaulted in content process in https://searchfox.org/mozilla-central/rev/af78418c4b5f2c8721d1a06486cf4cf0b33e1e8d/dom/ipc/BrowserChild.cpp#2042-2044 due to the document is suppressed on event handling for alert() call.

(In reply to Edgar Chen [:edgar] from comment #6)

And it is preventDefaulted in content process in https://searchfox.org/mozilla-central/rev/af78418c4b5f2c8721d1a06486cf4cf0b33e1e8d/dom/ipc/BrowserChild.cpp#2042-2044 due to the document is suppressed on event handling for alert() call.

Oh, this was introduced in bug 1309587.

Hmm, page could even just use event.preventDefault() in keyboard event handler to prevent exiting fullscreen. Chrome doesn't allow the default action of exiting fullscreen being prevented, i.e. event.preventDefault() won't prevent the default action of exiting fullscreen, but it can prevent entering fullscreen.

Masayuki, it seems GlobalKeyListener just ignore a preventDefaulted event in https://searchfox.org/mozilla-central/rev/af78418c4b5f2c8721d1a06486cf4cf0b33e1e8d/dom/events/GlobalKeyListener.cpp#92-94, we probably doesn't have any existing way that can avoid page preventDefault a xul command? What is your suggestion to handle this, i.e. avoid page to prevent exiting fullscreen by calling event.preventDefault()?

Flags: needinfo?(echen) → needinfo?(masayuki)
Group: firefox-core-security → core-security
Component: Security → DOM: Events
Product: Firefox → Core
Severity: -- → S2

Basically, Gecko does not dispatch keyboard events whose default actions are not cancelable. However, I'm not sure whether we should apply this rule for F11 here because (according to your comment,) Chrome dispatches keyboard events of F11 even in the cases. Therefore, not dispatching keyboard events might cause new web-compat issues.

If you stop dispatching F11 keyboard events only while it's in the fullscreen mode, you can call WidgetEvent::StopCrossProcessForwarding in EventStateManager::PreHandleEvent or somewhere in the main process.

If you won't stop dispatching F11 keyboard events, I think that you could set WidgetEvent::mFlags.mCancelable to false before dispatching it into the DOM tree.

Olli: Do you have any ideas?

Flags: needinfo?(masayuki) → needinfo?(smaug)

Ah, but for making the shortcut key customizable, we could need to consider it in GlobalKeyListener with adding new attribute to the <key>, perhaps around here.

(In reply to Masayuki Nakano [:masayuki] (he/him)(JST, +0900) from comment #9)

Basically, Gecko does not dispatch keyboard events whose default actions are not cancelable. However, I'm not sure whether we should apply this rule for F11 here because (according to your comment,) Chrome dispatches keyboard events of F11 even in the cases. Therefore, not dispatching keyboard events might cause new web-compat issues.

Oh, Chrome doesn't dispatch F11 event while browser is in fullscreen mode (I thought it dispatch but the event is not cancelled, but it actually doesn't dispatch at all).

Not dispatching F11 when we're in fullscreen mode sounds reasonable.

Flags: needinfo?(smaug)

Chrome behave differently on Mac where the shortcut for browser fullscreen is fn+F, it still dispatch the keyboard event but it seems not cancelable (i.e. calling preventDefault() won't prevent exiting fullscreen). And Chrome's behavior on Windows where the shortcut for browser fullscreen is also F11 is the same as Linux (event isn't dispatched at all).

I am not sure why Chrome behave differently on Mac. But I feel that it might make more sense to behave consistent on each platform? I will try to check Chromuim source code to see if I could find any clue.

I agree, we should try be consistent, even if Chrome isn't.

Group: core-security → dom-core-security

Yeah, then, we should not dispatch keyboard events of a shortcut key to exit fullscreen mode if and only if it's in the fullscreen mode.

Would it be enough to add reserved="true" to the relevant <key> elements?

Doesn't seem to work on Mac -- Cmd-shift-F always seems to work, as does mousing up to the top to bring up the real OS menu bar.

Locking someone into fullscreen is more of a DOS. Seems like if you're going to do this kind of spoof and the victim browses around in application-fullscreen mode, then any random page could just draw a picture of a browser and make the user think Firefox popped out of fullscreen.

Status: UNCONFIRMED → NEW
Ever confirmed: true

(In reply to :Gijs (he/him) from comment #16)

Would it be enough to add reserved="true" to the relevant <key> elements?

Unfortunately, no. We need to reserve it only while it's in the fullscreen mode because the command toggles the state. Perhaps, reserved command should be set at entering the fullscreen mode and removed at existing from it, just check it in GlobalKeyHandler dynamically, or split the command to enter and to exit and update enabled state of them at changing the fullscreen mode and reserve the exit key.

BTW, does the keyboard navigation with the buttons in the fullscreen mode work even if all keyboard events are preventDefault'ed by the web apps? If no, it could be that the simplest solution is, we always stop dispatching keyboard events while it's in the fullscreen mode.

(In reply to Masayuki Nakano [:masayuki] (he/him)(JST, +0900) from comment #19)

(In reply to :Gijs (he/him) from comment #16)

Would it be enough to add reserved="true" to the relevant <key> elements?

Unfortunately, no. We need to reserve it only while it's in the fullscreen mode because the command toggles the state.

I'm afraid I don't follow. Why would it be bad to reserve the key in non-fullscreen mode? AIUI all it means is that websites would not be able to prevent entering fullscreen. That doesn't seem unreasonable to me?

BTW, does the keyboard navigation with the buttons in the fullscreen mode work even if all keyboard events are preventDefault'ed by the web apps?

I'm not sure what you specifically mean with "keyboard navigation with the buttons". Assuming you're referring to tab/arrow navigation in the toolbox, I would expect it to work once you got focus into that area of the browser, as I wouldn't expect events to go to web content at all. Inside web content itself, I guess websites will need to be able to adjust behaviour for tab/shift-tab so I guess they could break the focus-switching behaviour completely if they wanted to...

If no, it could be that the simplest solution is, we always stop dispatching keyboard events while it's in the fullscreen mode.

(This too I'm a bit confused by - presumably users still need to be able to use input fields etc. in fullscreen mode, so not sure what you mean by not dispatching the events at all? Sorry for all the dumb questions...)

Flags: needinfo?(masayuki)

(In reply to :Gijs (he/him) from comment #20)

(In reply to Masayuki Nakano [:masayuki] (he/him)(JST, +0900) from comment #19)

(In reply to :Gijs (he/him) from comment #16)

Would it be enough to add reserved="true" to the relevant <key> elements?

Unfortunately, no. We need to reserve it only while it's in the fullscreen mode because the command toggles the state.

I'm afraid I don't follow. Why would it be bad to reserve the key in non-fullscreen mode? AIUI all it means is that websites would not be able to prevent entering fullscreen. That doesn't seem unreasonable to me?

Although I've not checked the other browsers' behavior. I assume that they allow web apps to prevent entering the fullscreen mode with keyboard event listeners, we should follow it. Otherwise, it's fine to make it always reserved. In my understanding, exiting from the fullscreen mode is more important than entering to the fullscreen mode because the fullscreen mode consumes the space in the screen from the other native apps.

BTW, does the keyboard navigation with the buttons in the fullscreen mode work even if all keyboard events are preventDefault'ed by the web apps?

I'm not sure what you specifically mean with "keyboard navigation with the buttons".

Ah, sorry. I was confused at the fullscreen mode UI of the <vidoe>.

If no, it could be that the simplest solution is, we always stop dispatching keyboard events while it's in the fullscreen mode.

(This too I'm a bit confused by - presumably users still need to be able to use input fields etc. in fullscreen mode, so not sure what you mean by not dispatching the events at all? Sorry for all the dumb questions...)

Sorry, this is too. I was confused at the fullscreen mode of the <video>.

(Sorry for the long delay to reply since I'm sick, I need some more days to restart my usual work.)

Flags: needinfo?(masayuki)

(In reply to Masayuki Nakano [:masayuki] (he/him)(JST, +0900)(still sick) from comment #21)

(Sorry for the long delay to reply since I'm sick, I need some more days to restart my usual work.)

No worries, please get well before replying! This bug can wait a bit.

Although I've not checked the other browsers' behavior. I assume that they allow web apps to prevent entering the fullscreen mode with keyboard event listeners, we should follow it. Otherwise, it's fine to make it always reserved. In my understanding, exiting from the fullscreen mode is more important than entering to the fullscreen mode because the fullscreen mode consumes the space in the screen from the other native apps.

Hm. Thanks for elaborating. I don't really understand why websites would want/need to prevent entering fullscreen. Preventing the keyboard shortcut would not prevent opening fullscreen via the browser menus or toolbar buttons. I'm not sure why we would want to give websites the opportunity to block one of these but not the other - I guess in case the shortcut is supposed to do something else inside the web app instead of toggling full screen? But then, that would still not work properly if the shortcut did always exit fullscreen (but didn't enter it).

I tested Chrome on macOS (where it now uses Fn+F to open fullscreen), and could not prevent entering fullscreen using this shortcut. However, reading up about the shortcut change, it seems cmd-ctrl-f is also still supported to enter full screen, and that shortcut was prevented. See also comment 13.

Assuming we want to do the same, we could of course fix this in DOM code, but I do wonder whether the simplest fix would be duplicating the <key> element, using one for entering and one for exiting, making the exiting one reserved, and enabling/disabling them based on whether we're in fullscreen at the moment.

Sorry for the long delay.

I don't really understand why websites would want/need to prevent entering fullscreen.

Web apps may want to use function keys for their shortcut keys. In this scenario, web apps must want to prevent any defaults of their shortcut keys, not just for entering fullscreen.

Preventing the keyboard shortcut would not prevent opening fullscreen via the browser menus or toolbar buttons.

Indeed, but the other browser commands associated with a shortcut key have same issue. So I think that the inconsistency is not a problem.

Once we allow to override F11 only at entering the fullscreen mode, the shortcut key of the web app may not work only when exiting from the fullscreen mode which is started without F11 key press. This inconsistent behavior (temporarily F11 is not available on the web apps) is not good, but I think that this is rarer than the cases F11 work as expected on web apps without fullscreen mode.

I tested Chrome on macOS (where it now uses Fn+F to open fullscreen), and could not prevent entering fullscreen using this shortcut.

I tested it on Chrome on Windows. Then, F11 for entering the fullscreen mode can be overridden. However, F11 key events are not fired for existing the fullscreen mode. This is what I'd love to do.

but I do wonder whether the simplest fix would be duplicating the <key> element, using one for entering and one for exiting, making the exiting one reserved, and enabling/disabling them based on whether we're in fullscreen at the moment.

Yeah, sounds like it's the best approach to fix this soon without risky changes.

Hmm, only one <key> element is registered into GlobalKeyListener if some have same key combinations. Therefore, the approach using multiple <key> elements do not work. Additionally, updating reserved attribute does not affect GlobalKeyListener because probably it's once initialized and not observing the mutations. I'll keep investigating which way is the simplest/safest fix.

Assignee: nobody → masayuki
Status: NEW → ASSIGNED

Ah, it seems that it's caused by a bug of the loop in GlobalKeyListener::WalkHandlersAndExecute.

Chrome for Windows does not dispatch keydown event for shortcut keys existing
from the fullscreen mode. Therefore, we can follow it.

For reserving only shortcut keys in fullscreen mode, we need to duplicate XUL
<key> elements which define the shortcut keys (only one in Windows/Linux,
but 3 in macOS). Then, their disabled attributes should be managed when
toggling the fullscreen mode.

Finally, we need to make XULKeySetGlobalKeyListener check the disabled
attribute of <key> elements because it's check in DispatchXULKeyCommand
in the final step:
https://searchfox.org/mozilla-central/rev/11a4d97a7b5cdfa133f4bda4525649f651703018/dom/events/KeyEventHandler.cpp#315-316

and it stops handling everything with doing nothing. I'm not sure whether this
was intentionally implemented or just a inefficient code which we didn't take
care the performance. However, I think that ignoring the disabled <key>
elements is reasonable behavior from <key> element users point of view.

(I found only one <key> which is disabled by default:
https://searchfox.org/mozilla-central/rev/11a4d97a7b5cdfa133f4bda4525649f651703018/browser/base/content/browser-sets.inc#225-233)

Group: dom-core-security → core-security-release
Status: ASSIGNED → RESOLVED
Closed: 1 years ago
Resolution: --- → FIXED
Target Milestone: --- → 115 Branch
Regressions: 1835570
Flags: sec-bounty? → sec-bounty-
Whiteboard: [reporter-external] [client-bounty-form] [verif?] → [reporter-external] [client-bounty-form] [verif?][adv-main115+]
Alias: CVE-2023-37210
Group: core-security-release
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: