Closed Bug 966532 Opened 7 years ago Closed 5 years ago

Address bar spoofing combined with hidden page replacement

Categories

(Firefox for Android :: General, defect)

26 Branch
ARM
Android
defect
Not set
normal

Tracking

()

RESOLVED FIXED

People

(Reporter: danutzu7, Unassigned)

Details

(Keywords: csectype-spoof, sec-low)

User Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.102 Safari/537.36

Steps to reproduce:

Hello,

I know that you've implemented this as a "feature" for saving screen space, but I'll do my best to explain why this is A BUG, not a feature.

The main problem is that the address bar in Firefox for Android doesn't display the current URL after the page was loaded. And this is a problem because it can very easy trick users to believe that scam pages are the original pages. Maybe I'll make myself clearer with an example.

Test tools:
- no-name phone with Android 4.0.4 installed;
- Firefox Mobile 26 installed from the Google Play;
- an website that opens new URLs using the << target="_blank" >> atribute, I've chosen facebook just to show how mainstream the problem can be;
- a scam page for the targeted website, this role will be played by http://daniel-tomescu.com/scam.php
- a decoy page, to reload the targeted website with the scam page, this role will be played by http://daniel-tomescu.com/xyztest.php

Test scenario:
1. I am the "attacker" and I'm just chatting on facebook with my "victim";
2. I give my victim a link to my decoy page: http://daniel-tomescu.com/xyztest.php ;
3. The victim taps on the link and the decoy page loads;
4. While loading, the decoy page executes the folowing javascript: <<< window.opener.location.replace('http://daniel-tomescu.com/scam.php'); >>>
5. The facebook tab reloads with the scam page, BUT THE VICTIM DOESN'T SEE THIS!!! because the focus is on the tab containing the decoy page;
6. When the victim returns to the facebook tab, it only sees the scam page and the title. If the scam page looks roughly like facebook, the victim will never suspect that he is on a scam page and will be tricked to so god-knows-what.

scam.php source:
<html>
<link rel="shortcut icon" href="fb.ico" type="image/x-icon">
<title>Madalina Baranga</title>

My cool scam page. lol
</html>



xyztest.php source:

<html>
<script>
window.opener.location.replace('http://daniel-tomescu.com/scam.php');
</script>

My cool page with some funny cat pictures.
</html>


Actual results:

Here are are some screenshots, maybe this will make it more clear about the attack scenario:
Me, with the "victim" on facebook:
http://s15.postimg.org/o8271a3d7/Screenshot_2014_02_01_00_36_58.png

What happens when the victim loads the decoy page:
http://s15.postimg.org/d771w9b4b/Screenshot_2014_02_01_00_47_42.png

The victim returns to the initial tab, but sees a scam page. ?!?!?
http://s15.postimg.org/fahh3xax7/Screenshot_2014_02_01_00_48_43.png

Please note that the title of the page, the page content, the presence of an SSL certificate, the favicon, are all available for the attacker to modify by his will, so he has all the tools to create a perfect copy of the targeted website.

"The problem with the web browsers is that the address bar is the only security indicator that the user can rely on!" (can't remember who said that, but it's a quote).

The problem is that by not showing the address of the page, the user has no clue where hi is on the web and I've provided you above with an working demo for that by using the window.opener.location property.


Expected results:

Well, first of all, the user should be notified all the time if a tab changes it's URL. Even if the tab lacks focus.

Second of all, when the user switches tabs, he should see by default the address bar containing the address of the website, NOT THE TITLE!

Third, I don't think it is a good idea to allow a tab to reload another tab. Why does window.opener.location.replace() method work in javascript when every other form of communication between tabs is forbidden? This is not the big problem, I've seen that all the modern browsers allow this and I'm too little to change that. But maybe you can. :)

~~~~~~~~~~~

Hopefully, I've proven my point: not showing the url in the address bar is a high security issue because users can be tricked to visit scam pages with the same title/content as the original, in the same tab, without any change notification, by doing only usual user stuff: clicking on links.

I haven't put much effort into making a good scam page because this is not the purpose of this demonstration.

If you need any additional details, please feel free to contact me.

Thank you!
Group: core-security
Flags: sec-bounty?
Thank you, Al Billings! I am really sorry for not checking the "security check" before submitting, I don't know what was on my mind. Sorry.
Just noting here that your example script is throwing [1] 

[1] Uncaught TypeError: Cannot read property 'location' of null
Hello Aaron,

This happens when you click on the link, but the link doesn't open in a new tab, so the window.opener is not set to anything (it really is null). 

To remake my scenario, pay attention to the following conditions:
- the link MUST be opened from a page where the target is set to "_blank", so it will open a new tab;
- just left click it (or tap it, if you are using a touch device); it won't work if you right click -> Open in new tab, it won't work if you hold the Ctrl key and left click on the link;

In the source code of tab 1, there should be something like <a href="http://daniel-tomescu.com/xyztest.php" target="_blank"> Click me </a>

bugzilla.mozilla.org opens links in the same tab, so just by clicking on it from this bug page won't work. Use facebook, twitter, vbulletin forums etc

If you have a hard time remaking my scenario, I could make a short video about it... Is it necessary?

Sorry for my bad English...
We understood that this sort of tradeoff when making Firefox for Android. This is mostly bug 605206. Bug 778216 is the main mitigation.
I am not sure you've taken into consideration all the security implications of showing the title instead of the URL. In the example I've provided in my initial post, you can see how the user can be tricked by only clicking a link. And this is because everything you show to a user by default can be spoofed by an attacker.

I get that it looks "fancy" to show the user the title, but this is wrong from two points of view:
- a developer doesn't really care about the webpage title, some sites doesn't even have a title set; developers care more about the domain (and the URL) because that is what users should remember. Remembering the domain name helps users get back on the site, remembering the title doesn't. 
Just ask a few people if they remember the title or the domain of their favorite payment website, file sharing website or social website. And please note that those are key-types of websites from an attackers point of view;

- displaying the title leaves the user clueless in case of being redirected on a scam page. He entered on a legitimate website, manually checked the URL just to be sure, then he clicks on a link (and this is really standard user behavior, can you imagine internet without clicking on links?!?) and when he returns on the initial website he'll have no idea about the security context of the page. What should he do, manually check again the URL? Can you imagine browsing on Android and being forced to manually check the URL every time you switch tabs? I can't... And I'm not talking only about advanced users, I'm taking about teenagers that are always in a hurry, I'm taking about people with little knowledge on security matters, they will never manually check the URL when switching tabs...

In the end, the trade resumes about what do you care more about: a fancy feature that is not that important for users and developers, or keeping your users safe?
I agree that this is essentially a dupe of bug 605206. The security implications of not making the URL (or at least: host) obvious have been brought up multiple times by various people as making phishing way easier.

What's new in this bug is replacing an existing tab via this trick:
window.opener.location.replace('http://daniel-tomescu.com/scam.php');

CCing the UX people to see if this makes them reevaluate 605206.
OS: Windows 8.1 → Android
Hardware: x86_64 → ARM
I'm not convinced this isn't a dupe of bug 605206, but since I was sad to see that wontfixed (for the reasons stated by the reporter here) I can confirm this one.

We did add a pref so that users and addons can force the display of the URL instead of the title, but that doesn't help very many people. My main hope there was that enough people would feel this threat that there'd be a popular add-on that made this switch.
Status: UNCONFIRMED → NEW
Ever confirmed: true
I've always been of the mind that there is far greater informational value to showing our users a page title by default, compared to the risk people have raised of not showing a URL. 

A 'normal' non-technical user (think of the 99% population of non-wizard user types we have) wouldn't have the technical know-how to recognize a spoofed site even if they saw the URL. For the remaining 1% who would, we have an easy to access pref they can flip in Settings. 

And to build on that, if what Mark is saying in https://bugzilla.mozilla.org/show_bug.cgi?id=605206#c37 is true, that we actually don't even have any evidence that showing a URL has any impact on the phishability of a page, then it's even harder for me to see the value of defaulting to a non-human-readable string (a URL) instead of a human-readable string (a title). 

I agree that Daniel has identified a security issue here, but it doesn't sound like showing a URL is the thing that will fix it.
I'm not a security expert, but:
window.opener.location.replace('http://daniel-tomescu.com/scam.php');

>5. The facebook tab reloads with the scam page, BUT THE VICTIM DOESN'T SEE THIS!!! because the focus is 
>on the tab containing the decoy page;

Should this be even possible?

http://stackoverflow.com/questions/8141417/how-to-get-access-from-cross-site-popup-to-window-opener

"That sounds like cross-domain scripting which is going to be prevented by security limitations; or am I reading the question incorrectly?"

Strangely, it works for me in Firefox. <<<<<<<<
@Ian Barlow,
For me, this is very simple, a black and white situation: showing the URL has a security value because the URL is an identifier of the webpage, while showing the title has no security value and can confuse people. 


Thank you all for your interest in this bug. Maybe we will come up with a solution for this situation because I think we can all agree that the scenario I've presented in my initial post is not normal.

So.. thank you for validating the bug!
Easier link for testing POC (reuses reporter links, but has the _blank thing):
http://sjeng.org/mozilla/facebook.html

Testing on mobile:
* Chrome: not vulnerable, always shows URL, Page title only used in tab thumbnail views
* Dolphin: not vulnerable, always shows URL, Page title on tabs
* Firefox: vulnerable, no way to see that the original page got redirected if you don't click the awesomebar

Testing on desktop:
* Chrome, Firefox: allow the redirect, but of course show the URL
* Internet Explorer: DOES NOT allow the redirect, it pops up a question on the "facebook" page whether a script from "scamsite-domain.com" is allowed to run.

So, basically, if we're going to maintain the UX decision that "URLs don't matter because they're too complicated", we should very strongly consider an IE-style doorhanger before allowing this kind of same-origin violation.

Related:
http://my.opera.com/hallvors/blog/2007/03/14/window-opener-and-security-an-unfixable-problem
I agree we should be doing something about window.opener. Ideally, we could just block it, though Hallvord's blog post indicates that this will break some sites. How big of a problem is that on mobile?

If we can't just block the behavior, showing a doorhanger on the tab that is being changed seems appropriate.
(In reply to Ian Barlow (:ibarlow) from comment #8)

> I agree that Daniel has identified a security issue here, but it doesn't
> sound like showing a URL is the thing that will fix it.

Agreed. And if the people in this bug really feel this is a security issue we had better find a solution that does not depend on "show the URL". That helps almost no one.
Summary: adressbar spoofing → address bar spoofing
> How big of a problem is that on mobile?

I can't tell you that.

What I can tell you is that cross-origin location.replace() is explicitly white-listed in implementation and the spec as being allowed because so many things depend on it.  Now they might be depending on it in the "cross-origin subframe" case, not the "cross-origin opener" case....

We could conceivably do something where if we open via target=_blank and the destination URI is not same-origin with us we cut the opener link.  We would need to see what other UA vendors think of that.
(In reply to Boris Zbarsky [:bz] from comment #14)
> > How big of a problem is that on mobile?
> 
> I can't tell you that.
> 
> What I can tell you is that cross-origin location.replace() is explicitly
> white-listed in implementation and the spec as being allowed because so many
> things depend on it.  Now they might be depending on it in the "cross-origin
> subframe" case, not the "cross-origin opener" case....
> 
> We could conceivably do something where if we open via target=_blank and the
> destination URI is not same-origin with us we cut the opener link.  We would
> need to see what other UA vendors think of that.

In the meantime, could we send a notification, with the front-end can catch, so we could notify the user that the tab changed without them knowing it?

I don't want to popup notifications anytime a tab changes location, only for this situation.
Hello again,

A bit offtopic, but I think it might be helpful: Sites like *.google.com, *.facebook.com, *.twitter.com allow users to open sites in a new tab, but they have a nice pattern:
1. they wrap the URLs to be opened in one of their own, like t.co/something or plus.url.google.com/something;
2. they open the wrapped URL in a new tab;
3. they check if the url contains malware/is blacklisted/ is safe;
4. they redirect the user to the new URL;

Google is the only one that actually blocks the window.opener property in step 3.

Just pointing out that one of the top companies in the industry has already seen this as a threat.
Can we define "this situation"?

Is it a background tab being navigated to a URL that's not same-origin with its current URL?  A background tab being navigated via a cross-site replace()/hrefsetter call?  Some combination of the two?
A background tab being navigated through an action from a JS file that resides on another domain, which I presume is your second case.

What are the cases for the first? An XSS attack that acts and redirects the page the moment it gets backgrounded?
> A background tab being navigated through an action from a JS file that resides on another
> domain

Bobby, do we have the caller principal by the time we land in Location code?

But consider also a page that opens a popup window that can load cross-domain things.  And then you click a link on that page to navigate the popup window... That's a cross-domain navigation of a background tab, but in terms of user perception totally different.  :(
Flags: needinfo?(bobbyholley)
>But consider also a page that opens a popup window that can load cross-domain things.  And then you
>click a link on that page to navigate the popup window

This is a pretty broken use case for mobile to begin with, I think? I don't think we have real popup windows.


(Might be Adblock as well :-)
> I don't think we have real popup windows.

Right, that's what puts the popup in a background tab....

My point is I would be very surprised if there are no sites out there doing that.
Right, but those provide a bad user experience now, at worst we're making it a little worse. I think we can live with this.

The way the IE permission popup works is that it seems to remember that "*.scam-domain-helper.com" is allowed to do the cross-site navigation. With your example that means you'd only need to dismiss the popup once? If the info who (host) requested who (tab) to navigate is available to the Android UI JS then making some "Always allow for host" thingie should be very doable. But maybe mfinkle should comment on that :)
(In reply to Boris Zbarsky [:bz] from comment #19)
> > A background tab being navigated through an action from a JS file that resides on another
> > domain
> 
> Bobby, do we have the caller principal by the time we land in Location code?

You mean nsContentUtils::GetSubjectPrincipal()? Certainly. In the cross-origin case, it'll go over Xrays.

There's no difference between Location and any other DOM interface these days, except for the fact that most Location methods do an explicit security check in C++ to deal with the inactive inner case.
Flags: needinfo?(bobbyholley)
Rereading this:

>A background tab being navigated via a cross-site replace()/hrefsetter call?
...
>A background tab being navigated through an action from a JS file that resides on another domain, which 
>I presume is your second case.
...
>But consider also a page that opens a popup window that can load cross-domain things.  And then you 
>click a link on that page to navigate the popup window

I'm thinking the case you mention wouldn't be caught by the rule you mentioned, but it would be by what I mentioned? A page opening a tab and then controlling that tab seems OK to me. It's the reverse that is problematic.
> In the cross-origin case, it'll go over Xrays.

That was the part I was verifying: that we can detect the cross-origin case inside C++ here.

> I'm thinking the case you mention wouldn't be caught by the rule you mentioned,

Actually, it would.

> A page opening a tab and then controlling that tab seems OK to me.

OK, so what we really need is to somehow tie things back to openers... I'm not quite sure how.
I wouldn't like this to die out in the perfect-is-the-enemy-of-good sense. bz, how hard is it to do the next best thing that might warn in more situations but is simpler to implement?

UX, would it be worthwhile to think about displaying the domain instead of the page title, if the domain was changed while the page was backgrounded? This is a) simpler b) doable entirely in Android browser.js - I think - c) defeats this attack. I would still prefer the doorhanger-style notification because it catches people's attention better, but if that turns out to give to many false positives, again, we can try the next best thing.
I'm changing the title to make it clear what we're trying to prevent. UX has made it clear they don't think the address bar is enough to protect most users.

Also needinfo bz for previous comment.
Flags: needinfo?(bzbarsky)
Summary: address bar spoofing → Address bar spoofing combined with hidden page replacement
> how hard is it to do the next best thing

Which thing is that?  What behavior are you aiming for?
Flags: needinfo?(bzbarsky)
The thing described in comment 18/19. I had the impression the caveat I mentioned in comment 24/25 complicated things.

Detect when a site that's in the background has it's location changed through cross-site scripting.
18/19 do not describe a "thing".  19 lists several different possible "things", and it's not clear to me which of them we want for this bug.
Can you then explain why they are "different things", and which of those "different things" we can detect without major infrastructure changes or an overly complicated patch, so we can make a judgment if we can likely just live with any false positives they give?
The fundamental question I want to understand is what we're trying to protect against.

It seems like we want to protect against certain page navigations when the window being navigated is in a hidden tab, possibly subject to the following restrictions:

1)  The window doing the navigating is not same-origin with the window being navigated.
2)  The URL being navigated to is not same-origin with the window being navigated.
3)  The window being navigated is its own .top (so a root window in the tab, not just a
    subframe).
4)  The window being navigated is the opener of the window doing the navigating.
5)  The window doing the navigating is not the opener of the window being navigated.
6)  The window doing the navigating is not in the same tab as the window being navigated.

Which of these restrictions do we actually want?  Rereading comment 18, it sounds like we want #1 for sure and do not want #2?  Do we care about #3?  

What about #6?  That is, do we care about good.com loading an evil.com subframe by accident, which then waits until good.com is in a background tab and navigates its .top?

For that matter, do we care about hidden tabs vs "hey, the user looked away from the phone for a few minutes; let's navigate the _foreground_ tab now"?

Oh, and I think #5 is not too bad to do (with some false positives if pages null out the opener), but #4 would take some work (keeping track of "real" openers when we don't right now, since pages can null out the opener).
Hello,

I've been working on a solution to prevent the window to change its location when the tab hasn't got focus. With the power of "copy-paste" from different sources, I came out with this: http://pastebin.com/LCNJWXcv

You can also test it here: http://daniel-tomescu.com/hasfocus.html

It seems to work as I expected (I find this strange, it happens rarely) on firefox mobile. Maybe it will be a starting point for you to build a client-side solution for this problem.

Cheers!
>I've been working on a solution to prevent the window to change its location when the tab hasn't got focus.

You don't want this - it basically breaks the web. Similarly, warning when a hidden tab changes location is trivial enough, but gives too many false positives. The discussion is which circumstances involving cross site scripting warrant a warning, and that's more tricky.

Popping up too many warnings is terrible for security - users learn to click them away without reading very rapidly.
I'm going to unhide this bug... this issue has been much discussed (in the old bugs, for instance) and spoofing is a well-known technique in general. Although we appreciate the demonstration in this bug it does not qualify for a bug bounty since it's a known issue.

Despite the claims in this bug about the importance of the title I'll note that the DESKTOP version of Firefox got rid of the title on Windows a long time ago (even having the space) and Australis is getting rid of it everywhere else I think (maybe not on Mac). I agree that a lot of users will be fooled regardless, but for those users who _do_ check (and there are lots of pages and articles reminding people to check) spoofing the URL is much much harder (especially if it's SSL) and less likely.
Assignee: nobody → mark.finkle
Group: core-security
Flags: sec-bounty? → sec-bounty-
A final point on the title/URL side discussion: showing the URL becomes actively misleading when it's

  http://www.facebook.com.mysite.com/spoof.html

On my large-screened HTC One in portrait mode, that shows as

  http://www.facebook.co…

which — if anything — increases the user's confidence.

Just about any URL is too big for a phone screen with common truncation techniques. For every counter-point (text narrowing, tablets in landscape mode…) one can rebut with "most users are on portrait phones" and "here's a longer domain name that still displays the issue".

You'd need to redefine "check the URL" as something other than "look at the address bar".
Indeed, unless the address bar is positioned with the rightmost bit of the hostname right-aligned in it...
Is www.facebook.com an eTLD?
(In reply to On vacation Aug 5-18.  Please do not request review. from comment #40)
> Is www.facebook.com an eTLD?

Oh, typo.

http://everybodyknowshowiliketospoof.wwwfacebook.com/

Or whatever "suffix looks valid" URL you wish to pick for this thought experiment!
Ah, fair.

That said, you could just as easily use "http://wwwfacebook.com", right?  Doesn't matter what the screen size is...  The only sane way to "check the url" in that case is to not look at the url at all, since you might well miss the lacking '.'.
Actually, the hostname+domain coloring/bolding we use on desktop (and even mobile?) would make those really obvious, so these examples don't prove anything.
This got some news today because someone mistook an old blog post for news, but anyway:
http://www.azarask.in/blog/post/a-new-type-of-phishing-attack/

Nice POC from a former collegue...in 2010 :-P
In bug 1111729 we changed the default to always show the URL in the toolbar.

However, the point about long sub-domains still applies here. Should we considering only showing the base domain? We already have logic in place to only highlight that part of the URL, so we could instead only show that in the toolbar until you click on it.

This conversation has come up recently - is there another bug filed about this issue?
Bug 605206 was about the original issue, we went back and forth a bit here whether this is a dupe or not.

I filed Bug 1236431 about the remarks I made on #mobile regarding origin display.
Both of the bugs GCP mentions are fixed. What's left for this bug?
Assignee: mark.finkle → nobody
We now show the page origin (public suffix + 1) by default, and the full URL when you click on it. The title is not shown by default. So I think this is fixed.
Status: NEW → RESOLVED
Closed: 5 years ago
Resolution: --- → FIXED
You need to log in before you can comment on or make changes to this bug.