Closed Bug 1641287 (CVE-2020-26979) Opened 5 years ago Closed 5 years ago

Malicious website can hijack Google search initiated from address bar

Categories

(Firefox :: Address Bar, defect, P1)

defect

Tracking

()

RESOLVED FIXED
84 Branch
Tracking Status
firefox84 --- fixed

People

(Reporter: xdavid, Assigned: daisuke)

References

(Regressed 1 open bug)

Details

(4 keywords, Whiteboard: [reporter-external] [client-bounty-form] [verif?][adv-main84+])

Attachments

(3 files, 2 obsolete files)

Attached video poc_2020_05_27.mov

Hi Team!

Summary:
Malicious website can listen for the keyup event, and perform a redirect when the user types a search term in the search bar and presses enter.

I found this issue after experiencing this weird behaviour on a website which was using the keyup listener to submit a form when enter is pressed.

Reproduction steps:

  1. Open the POC HTML included in this report
  2. Click on the searchbar and start typing to prepare a Google search
  3. Press enter quickly after typing the last character of the search query
  4. See the POC HTML redirect to YouTube inster of the expected search results appearing

I have noticed if the user waits before pressing enter after typing in the search query, the keyup event will not get dispatched.
I attached a POC video to see this issue in action. (length: 00:15)

POC HTML:

<html>
  <body>
    <h1 id="blur" style="display: none;padding-top: 30%;text-align: center">blur event, user maybe typing in searchbar!</h1>
    <script>

    window.addEventListener('focus', function(e) {
      document.body.style.backgroundColor = "white";
      document.getElementById("blur").style.display = "none";
    });

    window.addEventListener('blur', function(e) {
      document.body.style.backgroundColor = "red"
      document.getElementById("blur").style.display = "block";

      window.addEventListener('keyup', function() {
        window.location = "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
      });
    });

    </script>
  </body>
</html>

Thanks!
David

Flags: sec-bounty?

Not sure if this is search or address bar. mak, can you take a look?

Type: task → defect
Component: Security → Search
Flags: needinfo?(mak)

The video is showing the steps in the address bar, so moving across there. Leaving NI as this needs looking at.

Component: Search → Address Bar
Severity: normal → S2
Status: UNCONFIRMED → NEW
Ever confirmed: true
Priority: -- → P1

This also reproduces using the Search Bar. And I can imagine it would be for any input field that ends up calling into openLinkIn.

I was speaking with Gijs about this.
It may be due to the fact openLinkIn focuses the content window before the load https://searchfox.org/mozilla-central/rev/bc3600def806859c31b2c7ac06e3d69271052a89/browser/base/content/utilityOverlay.js#548
then the content window ends up getting the keyup event of the last typed letter.

I was expecting us to not send a chrome generated event down to content like that, but we don't seem to be checking them?
Olli, is this something frontend should handle, or should it be handled at the event handling level?

Flags: needinfo?(mak) → needinfo?(bugs)

What is the chrome generated event here?
Key events go to the focused element. So if window.focus() ends up causing some <browser> to be focused, key events go there.

Flags: needinfo?(bugs)

I'm sorry, I meant the keyup event target is a chrome element, so it looks like content can intercept those and sort of poll what was the last key event. Why don't we disallow key events generated by a chrome element to reach content windows? Can the opposite happen (chrome receiving a key event generated from a content element)?

Flags: needinfo?(bugs)

Does some chrome element generate key events? If so, it needs to be dispatched in rather unusual way from JS to reach child processes.
In general all the user input events come from the OS, go to the parent process, and if needed, are forwarded to a child process.

If there is a cancelable user input event in the parent process and you want to prevent it to end to the child process, call preventDefault() ?
https://searchfox.org/mozilla-central/rev/bc3600def806859c31b2c7ac06e3d69271052a89/widget/BasicEvents.h#200,210

Flags: needinfo?(bugs)

Thanks, considered there's no boundary check, and it doesn't look like the basic <input> widget should do it, I guess we'll need to fix autocomplete-input (or just the search bar, tbd) and the urlbar to preventDefault() "keyup".

Group: firefox-core-security
Flags: sec-bounty? → sec-bounty-

I can't reproduce this as described (hitting enter really quickly).

I can get the POC to navigate to youtube after focusing back on the tab if I Alt or Control+Tab back to that tab, because the page seeings me releasing the Tab key to focus on the page. Using the mouse to focus back on the tab does not cause any navigation.

I am still able to reproduce the issue on Firefox 81.0, on macOS 10.15.7.

Works with the same POC, just like in the attached video.

I have taken a look at this a bit, could confirm this is still reproducible in current m-c.

I tried some.
First, tried to call preventDefault() at here in UrlbarInput.jsm, but it could not resolve this issue.
Next, stopped to call w.focus() in utilityOverlay.js as well, this also could not work.

I asked Masayuki about this issue.
He gave thinking that we start to navigate the page, but perhaps if keyup event is fired when the content is still active, the event may arrive to the content.
Also, he gave an idea of assuming the above thinking.
When navigating with urlbar, marks the document or browsing context as zombie etc, then if we can stop to send the event to the document marked as zombie, this issue will be fixed.

I want to try to fix with Masayuki’s way, but what do you think, Olli?

Flags: needinfo?(bugs)

Sounds complicated. Is the issue such that we move focus to child process in a keypress event and thus calling preventDefault on keyup doesn't work, since it already goes to child process? If that is the case, could we focus child process only after keyup?

Flags: needinfo?(bugs)

(In reply to Olli Pettay [:smaug] from comment #11)

Sounds complicated. Is the issue such that we move focus to child process in a keypress event and thus calling preventDefault on keyup doesn't work, since it already goes to child process? If that is the case, could we focus child process only after keyup?

keyup event is an independent event of physical device so that it can be dispatched:

  • without following keydown nor keypress events
  • after auto-repeated keydown and keypress events

So, widget can receive native keyup event anytime, and that means that PresShell or EventStateManager needs to manager for each physical key in strict speaking. However, it's more complicated since keyup event may not be fired if user releases a key after activating another app. So, I think that if chrome script or docshell can mark a document which will be reloacated by chrome script as zombie or disabled to suppress to run any event handlers in it with user input events.

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

So, I think that if chrome script or docshell can mark a document which will be reloacated by chrome script as zombie or disabled to suppress to run any event handlers in it with user input events.

There's no guarantee that the attempt to navigate from the address bar will actually load another page. The current page might have a beforeunload handler and stop the unload.

And typing to locationbar may just add #fragment so that page is scrolled to a new position.

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

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

So, I think that if chrome script or docshell can mark a document which will be reloacated by chrome script as zombie or disabled to suppress to run any event handlers in it with user input events.

There's no guarantee that the attempt to navigate from the address bar will actually load another page. The current page might have a beforeunload handler and stop the unload.

Yeah, I think that we should make PresShell stop delivering user input to the old document.

(In reply to Olli Pettay [:smaug] from comment #14)

And typing to locationbar may just add #fragment so that page is scrolled to a new position.

Oh, that's what I didn't expect...

Thank you very much for all your feedback!
It was so helpful fo me.

So, next, as Ollie suggested, I have investigated from focus side.
As a result, if we comment out the following codes that focus on the browser, could capture the keyup event of Enter in the urlbar, not the content document.

  1. https://searchfox.org/mozilla-central/rev/35245411b9e8a911fe3f5adb0632c3394f8b4ccb/browser/components/urlbar/UrlbarInput.jsm#2317
  2. https://searchfox.org/mozilla-central/rev/35245411b9e8a911fe3f5adb0632c3394f8b4ccb/browser/base/content/utilityOverlay.js#703

So, as suggested, I'm going to try to fix it so that focuses on the browser at keyup instead of keydown.

Thank you once again.

Assignee: nobody → daisuke
Blocks: 1673299
Status: NEW → RESOLVED
Closed: 5 years ago
Resolution: --- → FIXED
Target Milestone: --- → 84 Branch

Changing Summary to reflect reality.

Summary: Malicious website can hijack Google search initiated from search bar → Malicious website can hijack Google search initiated from address bar
Regressions: 1676054
No longer regressions: 1673357
Regressions: 1679641

Hi guys,

I'm sorry to say that I still can reproduce this bug by following the steps given by Tom in comment #8:

(In reply to Tom Ritter [:tjr] (ni? for response to sec-[advisories/bounties/ratings/cves]) from comment #8)

I can't reproduce this as described (hitting enter really quickly).

I can get the POC to navigate to youtube after focusing back on the tab if I Alt or Control+Tab back to that tab, because the page seeings me releasing the Tab key to focus on the page. Using the mouse to focus back on the tab does not cause any navigation.

I tested this on the latest nightly 85.0a1 (2020-12-04) (64-bit) on a new and old profile. This bug is also present on Beta 84.0b8 (64-bit)

Flags: needinfo?(daisuke)

Hi Florencia!
Thank you very much for letting me know.
Yes, I also could reproduce the issue.
I will take a look (but I may do in another bug because it seems that the issue is not related to addressbar.)

Flags: needinfo?(daisuke)
Whiteboard: [reporter-external] [client-bounty-form] [verif?] → [reporter-external] [client-bounty-form] [verif?][adv-main84+]
See Also: → 1681217
Attached file advisory.txt (obsolete) —
Attached file advisory.txt (obsolete) —
Attachment #9192449 - Attachment is obsolete: true
Attached file advisory.txt
Attachment #9192455 - Attachment is obsolete: true
Alias: CVE-2020-26979
Flags: sec-bounty-hof+
Regressions: 1710260
Regressions: 1749397
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: