Closed Bug 1114343 Opened 10 years ago Closed 9 years ago

Origin spoofing when URL is copied to the URL bar

Categories

(Firefox :: Address Bar, defect)

34 Branch
defect
Not set
normal
Points:
2

Tracking

()

RESOLVED FIXED
Firefox 38
Iteration:
38.1 - 26 Jan

People

(Reporter: gabor, Assigned: Gijs)

Details

(Keywords: csectype-spoof, sec-low)

Attachments

(2 files, 2 obsolete files)

Attached file phishing-poc.html
User Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:34.0) Gecko/20100101 Firefox/34.0
Build ID: 20141126041045

Steps to reproduce:

1. Copy and paste a long URL in the address bar so that the first part (domain name) of the URL becomes hidden
2. Press enter
3. The page redirects or changes the URL with JavaScript to another long URL



Actual results:

The first part of the new URL remains hidden, and the shown part can be used to spoof the new domain.


Expected results:

After copy and pasting a URL, the cursor should move back to the front of the URL and the address bar should remain left-aligned. This is what Chrome and IE currently does.

This is similar to bug 991503 but not identical. That bug requires the user to change the URL bar alignment to right, while in this case, all he needs to do is copy and paste a URL. It enables much easier phishing scenarios.

A plausible phishing scenario:
1. The attacker sends an email to the target person. The email is HTML based and is formatted like a Google Docs invite to open a presentation.
2. The link in the invite mail is non-clickable, and the text says: 'Click on the following link or copy it to the URL bar to open the presentation:'. The user will probably copy and paste the URL, thinking that there was a formatting error that made the link non-clickable.
3. The link itself is copied from a Google search results page (so it begins with www.google.com/...) and redirects to an attacker controlled domain, that supports HTTPS.
4. The attacker controlled domain, when the referer equals the link sent, redirects to the HTML page containing the URL spoofing code, with a very long arbitrary hash text (phishing.html#paddingpaddingpadding...).
5. The URL spoofing JS code measures the width of the browser window and replaces the hash with "# https://accounts.google.com/ServiceLogin        " with enough space at the end to achieve perfect alignment to spoof the domain. Since the site is HTTPS, the lock icon will appear near the spoofed domain.
6. The user enters his credential, thinking that the shared presentation needs authentication before it can be accessed.
7. The credentials are stored on the attacker domain and then the user is redirected to the actual shared presentation that is accessible without authentication.
(In reply to Gábor Molnár from comment #0)
> 3. The link itself is copied from a Google search results page (so it begins
> with www.google.com/...) and redirects to an attacker controlled domain,
> that supports HTTPS.
> 4. The attacker controlled domain, when the referer equals the link sent,
> redirects to the HTML page containing the URL spoofing code, with a very
> long arbitrary hash text (phishing.html#paddingpaddingpadding...).

In my testing, if the document location (rather than just the hash/ref) changes, the urlbar's contents will no longer stay in alignment, so this hypothetical scenario is not actually possible. You will need to convince the user to actually paste in a link as long as is required into the urlbar - a link, no less, which will start with the attacking domain - which IMO greatly reduces the effectiveness of the phishing attack.

I'm tempted to mark sec-low and to open this up, like bug 991503, but I'll wait for other people to chime in.
Status: UNCONFIRMED → NEW
Component: Untriaged → Location Bar
Ever confirmed: true
OS: Mac OS X → All
Hardware: x86 → All
I've also tested it with domain change and it works for me. Here's how to test it:
1. Go to https://gabor.molnar.es and whitelist my expired cert (sorry for that)
2. Search for gabor.molnar.es in Google.
3. Copy the search result link to the front page of the site, and append &secret=123456789 to it.
4. Copy and paste the modified link into the address bar and press enter.
5. You should be redirected to https://gabor.molnar.es/p.html#paddingpadding... and then the JS code should change the hash to "# https://accounts.google.com/ServiceLogin   ..." with enough space at the end for good alignment

Note: if the alignment is not perfect, but you don't see the whole domain part of the new url, it works but either I messed up the JS code or your browser window is too wide (in the latter case, try to append some junk at the initial google search result link and it should work)
One more thing already stated in the first PoC, but not here directly: the width calculation code is calibrated to work on a default layout Firefox (no extension icons, non-resized URL bar, etc.) running on Windows 7. Default layout on other operating systems should work too after some tweaking.

On the other hand, I believe that for non-default layouts (extension icons, etc.) it can not work because AFAIK it's impossible to measure the exact width of the URL bar and this is a required input for the code.
Why aren't we always displaying the URL from the beginning?
Group: core-security
(In reply to Daniel Veditz [:dveditz] from comment #4)
> Why aren't we always displaying the URL from the beginning?

Because if you type at the end, the cursor should show, and after a paste, your cursor is at the end.

A simplistic workaround would be to always reset the input field's selectedIndex onblur, but that is also quite a user-hostile workaround...
(In reply to Gábor Molnár from comment #2)
> I've also tested it with domain change and it works for me. Here's how to
> test it:
> 1. Go to https://gabor.molnar.es and whitelist my expired cert (sorry for
> that)
> 2. Search for gabor.molnar.es in Google.
> 3. Copy the search result link to the front page of the site, and append
> &secret=123456789 to it.
> 4. Copy and paste the modified link into the address bar and press enter.
> 5. You should be redirected to

I'm not redirected. I'm assuming you meant "put it at the end of the google URL", which just redirects me to the homepage. If you want me to url-encode it so that the Google page redirects to:
https://gabor.molnar.es/?secret=123456789

(I'm assuming you really want a ? rather than a & here)

then that breaks the automatic redirect and makes google ask whether I really want to go there ("This page is trying to send you to..."), and even clicking 'yes' still shows me your homepage.

What am I missing? (sorry for the trouble, but it *would* be useful if we had a good testcase here :-) )
Flags: needinfo?(gabor)
No problem, let's try to figure it out. So I have a Rewrite rule in my .htaccess like this:

    RewriteCond %{HTTP_REFERER} secret=123456789
    RewriteRule ^$ /p.html#paddingpaddingpadding...  [NE,R=302]

So yes, I meant "put it at the end of the google URL", but it should work anywhere in the URL! Is your search result URL https? If it is, it doesn't send a referer to my HTTP based front page (and my HTTPS front page is not indexed by google since the cert is expired :( ) Maybe try with HTTP if it is HTTPS now.

These search result URLs expire after some time, and after that, they show the warning you see. After obtaining a new link, the warning should disappear.

Aletrnatively, you could just create and host a HTML page on your own with a link to my front page and open it with "#paddingpaddingpadding.....secret=123456789" hash and then click on the link. I believe that it should work too.
Flags: needinfo?(gabor)
A correction to the last sentence: the hash is not included in the referer so you would actually have to replace '#' with '?' but otherwise it should work. Here's my test URL (same domain as the target, but should work cross domain too):

http://gabor.molnar.es/tmp/test.html?paddingpaddingpaddingpaddingpaddingpaddingpaddingpaddingpaddingpaddingpaddingpaddingpaddingpaddingpaddingpaddingpaddingpaddingpaddingpaddingpaddingpaddingsecret=123456789
And the redirection (or rather, the lack of redirection) is somehow cached so you'll have to disable the cache to properly see it.
Flags: needinfo?(gijskruitbosch+bugs)
(In reply to Gábor Molnár from comment #7)
> Is your search result URL https? If it is, it doesn't
> send a referer to my HTTP based front page (and my HTTPS front page is not
> indexed by google since the cert is expired :( ) Maybe try with HTTP if it
> is HTTPS now.

Ah. This will have been the problem; I tried changing the http bit to https, and that broke the redirect, which then broke the referer detection. I can reproduce with http:// .

Leaving needinfo because I want to figure out how to fix this, too... :-)
This WFM, but I don't know if this is the best place to do this. Dao, can you comment as to whether you think there's a better place to do this? onLocationChange or something?
Attachment #8547569 - Flags: feedback?(dao)
Assignee: nobody → gijskruitbosch+bugs
Status: NEW → ASSIGNED
Flags: needinfo?(gijskruitbosch+bugs)
Comment on attachment 8547569 [details] [diff] [review]
set selection after handling a navigation command, f?dao

There are cases in this method where this doesn't seem to make sense. I think the next best place to put this is the inline loadCurrent function. Also, a brief comment would be nice.
Attachment #8547569 - Flags: feedback?(dao) → feedback+
Attachment #8548851 - Flags: review?(dao)
Iteration: --- → 38.1 - 26 Jan
Points: --- → 2
Flags: qe-verify-
Flags: in-testsuite-
Flags: firefox-backlog+
Attachment #8547569 - Attachment is obsolete: true
Comment on attachment 8548851 [details] [diff] [review]
ensure start of URL is visible when user navigates,

>             function loadCurrent() {
>               openUILinkIn(url, "current", {
>                 allowThirdPartyFixup: true,
>                 disallowInheritPrincipal: !mayInheritPrincipal,
>                 allowPinnedTabHostChange: true,
>                 postData: postData
>               });
>+              // Avoid spoofing attacks by ensuring the start of the URL is
>+              // visible now that we navigate:
>+              this.selectionStart = this.selectionEnd = 0;

Does this even work? I would think it doesn't, because "this" isn't what we need within this function.
Attachment #8548851 - Flags: review?(dao) → review-
D'oh. I could have sworn I tested this, but here we are...
Attachment #8550315 - Flags: review?(dao)
Attachment #8548851 - Attachment is obsolete: true
Comment on attachment 8550315 [details] [diff] [review]
ensure start of URL is visible when user navigates,

>+              // Avoid spoofing attacks by ensuring the start of the URL is
>+              // visible now that we navigate:
>+              this.selectionStart = this.selectionEnd = 0;

Since it involves copy & paste or otherwise typing the location bar, I think "spoofing attack" is a little bit of a stretch. Seems more like a basic user experience issue.

>             }

missing semicolon
Attachment #8550315 - Flags: review?(dao) → review+
w/ updated comment:

remote:   https://hg.mozilla.org/integration/fx-team/rev/e73753a89c08
Whiteboard: [fixed-in-fx-team]
https://hg.mozilla.org/mozilla-central/rev/e73753a89c08
Status: ASSIGNED → RESOLVED
Closed: 9 years ago
Resolution: --- → FIXED
Whiteboard: [fixed-in-fx-team]
Target Milestone: --- → Firefox 38
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: