Closed Bug 1404513 Opened 7 years ago Closed 6 years ago

Appending a script tag with a remote src in a promise on a window focus event can prevent/hijack navigation via the address bar

Categories

(Core :: DOM: Navigation, defect, P2)

64 Branch
defect

Tracking

()

RESOLVED DUPLICATE of bug 1263100

People

(Reporter: gshively11, Unassigned)

Details

(Keywords: reporter-external)

User Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36

Steps to reproduce:

Sample plnkr here: http://plnkr.co/edit/ZiQINpgI5nYgZ6ew8Zzp?p=info
Here's the url for testing the sample: http://run.plnkr.co/plunks/wuJNfb6zuvlAe2axV0Ee/

1. Add a listener on the focus event of the window
2. In the listener, create a promise that does the following: 
 - creates a new script element:
 - script.src set to a valid url that returns valid javascript
 - script.onerror set to a function that rejects the promise
 - append the script element to the document body 
3. Add a catch to the promise that calls window.location.assign with some url

To see this in action, use the url mentioned above.  Open it in a new tab, then try to enter a new url into the address and hit enter.

This bug could be used to redirect users to a website spoofing some commonly visited website (e.g., facebook) in an attempt to phish their credentials.  If a user happened to type "facebook.com" into the address bar, then the redirect hijack could seem very convincing (the url would be a giveaway, but if you enter a site into the address bar, you don't except to be sent somewhere else).


Actual results:

If you used the sample url mentioned above, you should have been redirected to an image of Admiral Ackbar announcing the existence of a trap!


Expected results:

You should have navigated to whatever url you entered into the address bar.
Smaug, can you suggest someone who might be able to investigate this?
Flags: needinfo?(bugs)
Hmm, I assume this is possible in many different ways.
Group: firefox-core-security → core-security
Component: Untriaged → Document Navigation
Product: Firefox → Core
Perhaps Samael would be interested in to take a look.
Flags: needinfo?(bugs)
Flags: sec-bounty?
Group: core-security → dom-core-security
Why does the relative path load fail? If it's because we're running one site's code against a new origin that's probably bad. If it's because we cancel things during navigation then that's probably OK.
Flags: needinfo?(bugs)
Samael, feel free to unassign this if you're too busy elsewhere.
Assignee: nobody → sawang
Priority: -- → P2
(In reply to Daniel Veditz [:dveditz] from comment #4)
> Why does the relative path load fail? If it's because we're running one
> site's code against a new origin that's probably bad. If it's because we
> cancel things during navigation then that's probably OK.

My understanding is that after you focus to the address bar, type an URL, and press enter to leave the address bar,
it would generate the last focus event to the web page and attach one more script element. 
It's almost impossible that the the script would be loaded before the loading of what URL you typed in address bar starts, 
so the script loading is eventually canceled.

The stack rr gave me is (on loading of the URL typed in address bar starts)

#3  0x00007f2885b6a42c in mozilla::net::HttpChannelChild::Cancel(nsresult) (this=0x7f286ee21000, status=nsresult::NS_BINDING_ABORTED)
    at /home/freesamael/Repos/gecko-unified/netwerk/protocol/http/HttpChannelChild.cpp:2215
#4  0x00007f2885626b2d in mozilla::net::nsLoadGroup::Cancel(nsresult) (this=0x7f28821b4c00, status=nsresult::NS_BINDING_ABORTED)
    at /home/freesamael/Repos/gecko-unified/netwerk/base/nsLoadGroup.cpp:261
#5  0x00007f2886aa6b27 in nsDocLoader::Stop() (this=0x7f2878978800) at /home/freesamael/Repos/gecko-unified/uriloader/base/nsDocLoader.cpp:246
#6  0x00007f288c081ff5 in nsDocShell::Stop() (this=0x7f2878978800) at /home/freesamael/Repos/gecko-unified/docshell/base/nsDocShell.h:200
#7  0x00007f288c027017 in nsDocShell::Stop(unsigned int) (this=0x7f2878978800, aStopFlags=1) at /home/freesamael/Repos/gecko-unified/docshell/base/nsDocShell.cpp:5659
#8  0x00007f288c03a2e9 in nsDocShell::InternalLoad(nsIURI*, nsIURI*, mozilla::Maybe<nsCOMPtr<nsIURI> > const&, bool, nsIURI*, unsigned int, nsIPrincipal*, nsIPrincipal*, unsigned int, nsTSubstring<char16_t> const&, char const*, nsTSubstring<char16_t> const&, nsIInputStream*, long, nsIInputStream*, unsigned int, nsISHEntry*, bool, nsTSubstring<char16_t> const&, nsIDocShell*, nsIURI*, bool, nsIDocShell**, nsIRequest**) (this=0x7f2878978800, aURI=
    0x7f28701f7cd0, aOriginalURI=0x0, aResultPrincipalURI=..., aLoadReplace=false, aReferrer=0x0, aReferrerPolicy=0, aTriggeringPrincipal=
    0x7f28821c20b0, aPrincipalToInherit=0x7f286f2a6820, aFlags=4, aWindowTarget=..., aTypeHint=0x0, aFileName=..., aPostData=0x0, aPostDataLength=-1, aHeadersData=0x0, aLoadType=1, aSHEntry=0x0, aFirstParty=true, aSrcdoc=..., aSourceDocShell=0x0, aBaseURI=0x0, aCheckForPrerender=false, aDocShell=0x0, aRequest=0x0)
    at /home/freesamael/Repos/gecko-unified/docshell/base/nsDocShell.cpp:10782
#9  0x00007f288c033f6a in nsDocShell::LoadURI(nsIURI*, nsIDocShellLoadInfo*, unsigned int, bool) (this=0x7f2878978800, aURI=0x7f28701f7cd0, aLoadInfo=0x7f286f10b8e0, aLoadFlags=3932160, aFirstParty=true) at /home/freesamael/Repos/gecko-unified/docshell/base/nsDocShell.cpp:1612
Flags: needinfo?(bugs)
Status: UNCONFIRMED → NEW
Ever confirmed: true
I'd like to suggest a higher security rating than sec-low for this one, based on the examples on https://wiki.mozilla.org/Security_Severity_Ratings.  I think the following apply to this bug:

From sec-high: 

"Exploitable web vulnerabilities that can lead to the targeted compromise of a small number of users."
"Spoofing of full URL bar or bypass of SSL integrity checks" (not exactly spoofing the url bar, but similar)

From sec-moderate: "The lack of standard defense in depth techniques and security controls."

I would think at minimum this would be sec-moderate, but my viewpoint is obviously a bit biased considering the sec bounty program.  Thoughts?
Hi folks, it's been a while without any movement on this bug. If this bug isn't going to qualify for the bounty program, or it isn't going to be fixed anytime soon, I'd like to disclose it publicly by publishing a blog entry. I still believe this bug has the potential to do significant harm to users, so I'm surprised it's been mostly ignored thus far. Please reply in the next few days if you want me to keep the bug private for a period of time. Thanks!
There are a few other more risky security bugs I'm working on, so I haven't been able to start working on this one. Sorry about that.

I don't know how much we want to keep the information private. Maybe Daniel can answer it.
Flags: needinfo?(dveditz)
Thanks for the update Samael, I'll refrain from publicizing anything until we can determine an appropriate timeframe to do so.
If you do end up publishing this please let us know.
Flags: needinfo?(dveditz)
Sorry, we'll need someone else to take on this.
Assignee: freesamael → nobody
testcase no longer reproduces. Looks like it's still there on plnkr.co but can't be sure it's the same (would have been nice to have the PoC as a static attachment).
Status: NEW → RESOLVED
Closed: 6 years ago
Flags: sec-bounty? → sec-bounty-
Resolution: --- → WORKSFORME
Hey Daniel, I just tested this on Firefox 62 using the plinker in the original submission and the bug still exists. Coincidentally, I just started the process of a writing a blog article about this bug this morning and was going to post here about coordinating a release date.

Are you trying to reproduce this on a newer version than the 62 release?
Also, Daniel, assuming I'm correct about this bug still being active, can I get approval from Mozilla to publish an article about it? I'm happy to work on scheduling the release with you if you still want to tackle a fix before it goes public.
Status: RESOLVED → REOPENED
Resolution: WORKSFORME → ---
Version: 56 Branch → 64 Branch
ni? on dveditz for comment 15.
Flags: needinfo?(dveditz)
Version: 64 Branch → 62 Branch
Hey guys, it's been a few months. If I don't hear from you soon I'm going to assume this bug is fair game to publish.
Version: 62 Branch → 63 Branch
Version: 63 Branch → 64 Branch

Grant asked on bug 1518942 whether this bug is a dupe of bug 1263100 as well. This bug doesn't use beforeunload (like bug 1263100 and its dupes) but:

(In reply to Grant Shively from comment #5)

it uses focus instead. Navigating via the address bar triggers one final focus on the page, and we figured out a way to detect that last focus, so we use it to trigger an asynchronous window.location.assign, which is the heart of the bug. This method doesn't hijack as many navigation methods as beforeunload does, but it's still using the same core bug.

:qdot, do you think there's any point keeping these separate? (I'll add some more context on bug 1263100 in a bit.)

Flags: needinfo?(kyle)

I should mention that we discovered the whole remote script src tag onerror thing from the original submission is unnecessary. Any network request can be used to trigger code on the last page focus before navigation:

https://826pz3mzpj.codesandbox.io/

window.addEventListener("focus", () => {
fetch("https://826pz3mzpj.codesandbox.io/file.txt").catch(
() => window.location.assign("https://media2.giphy.com/media/lk0TFUdop2JTW/giphy.gif")
);
});

:gijs Yeah, that should be fine. I think a few of our other onunloadbefore issues could probably just be pointed there too. With the spec discussion happening there, it's a good outline of the general problem a lot of these bugs encompass.

Flags: needinfo?(kyle)

(In reply to Grant Shively from comment #15)

can I get approval from Mozilla to publish an article about it?

Given the similarity in effect to a public bug and it being sec-low, sure.

Flags: needinfo?(dveditz)

(In reply to Kyle Machulis [:qdot] [:kmachulis] (if a patch has no decent commit message, automatic r-) from comment #20)

:gijs Yeah, that should be fine. I think a few of our other onunloadbefore issues could probably just be pointed there too. With the spec discussion happening there, it's a good outline of the general problem a lot of these bugs encompass.

Alright, let's dupe this over then.

Status: REOPENED → RESOLVED
Closed: 6 years ago6 years ago
Resolution: --- → DUPLICATE
Group: dom-core-security
You need to log in before you can comment on or make changes to this bug.