New issue
Advanced search Search tips
Note: Color blocks (like or ) mean that a user may not be available. Tooltip shows the reason.

Issue 711772 link

Starred by 2 users

Issue metadata

Status: Fixed
Owner:
Closed: May 2017
Cc:
Components:
EstimatedDays: ----
NextAction: ----
OS: All
Pri: 2
Type: Bug-Security
Team-Security-UX



Sign in to add a comment

Subframe navigations can be used to add domains to history

Reported by ashis...@gmail.com, Apr 14 2017

Issue description

VULNERABILITY DETAILS
After Moxie Marlinspike introudced attacks via SSLStrip, HSTS was introduced as a way of battling MITM's on second visits. 
I believe the below stated attack in a similar way can make use of auto-complete functionality in browsers (including chrome) and manipulating homoglyph guidelines in place
that convert any mixed character sets to puny codes, and inject a site that looks awfully similar but is actually to a similar looking top level domain into a browser history.
Browsers will then use this new site to auto-complete as soon as a user types in first letter. For example f for facebook.com and fill it with homoplyphed site as shown
in screenshot attached. User will almost certainly hit enter to go to the site enabling a bypass of HSTS and an execute of MITM with a simple proxy that will then do 
url-rewriting from facebook.com to facebook.сом for example which is what i used in my attack. This problem is not limited to Chrome however i am choosing to report to Google
as my attacks were tested on Chrome. Below attack will not perform a SSLStrip but only show how to get the malicious domain into history. 
Whats good to note is this method also bypasses an favorites that user may have set that would normally be suggested first. 

VERSION
All? 

REPRODUCTION CASE
For this attack to work i am assuming MITM has been achieved via either DNS/Arp spoofing. Goal here is to bypass HSTS.
As stated above lets make user go to facebook.com as facebook does use HSTS. So we create a url facebook.сом which when suggested looks similar enough for our purposes. 
Browsers including Chrome will not replace .сом with puny code as characters were not actually mixed, They are all cyrillic and not part of the domain name. As long as
the characters within TLD are not mixed the browser will eventually attempt to get to the site. 
Attacker then listens in on HTTP traffic and activly replaces </body> tag (as example) with code below

<script type="text/javascript">
var count = 0;
function myFunction() {
	count = count + 1;
	document.getElementById('iframeid').src = document.getElementById('iframeid').src + "0";
	if (count < 4) {
	setTimeout(myFunction, 200);
	}
}

</script>
</head><body onload="myFunction();">
<iframe id="iframeid" style="visibility:hidden;display:none" src="http://facebook.сом/pages?try=0" />
</body>

The count was tested on chrome to be the point where the new domain will make it as first suggestion. The iframe will attempt to load http://facebook.сом/pages?try=0
The attacker also listens for this page and returns following page for it and produces a code 200. This is necessary as the browser must think this site exists
in order to show it in results. Now since i dont want this random pages?try url to show in suggestsions i as attacker return the following page.

<html>
	<body>
	<script type="text/javascript">
		var stateObj = { foo: "bar" };
		history.pushState(stateObj, "facebook", "http://facebook.сом");		
		</script>
	</body>
</html>


The page in this case will be loaded 5 times and http://facebook.сом seems to have been a good enough site for browser to put it in history (compare screenshot1
before attack vs screenshot2 post attack, user just types f) The first page can be actually loaded with a whole lot of url's that look similar but take full 
advantage of the attack. As soon as user hits this new facebook.сом request goes out of HTTP! and i was very easily able to SSLStrip https://facebook.com and replace
not just with http but http://facebook.сом. Ofcourse after deleting the HSTS header etc. but thats out of scope for this attack. I used fiddler to return the pages above
but can be achieved with a simple python proxy. Ive attached the files i used for attack and screenshot to my fiddler responder. 



 
screenshot1.png
8.2 KB View Download
screenshot2.png
12.4 KB View Download
frame.htm
370 bytes View Download
index.htm
846 bytes View Download
fiddler.png
10.6 KB View Download

Comment 1 by ashis...@gmail.com, Apr 14 2017

viewing the pages attached turn .сом to A>< due to encoding issues. download for actual page or just copy paste from the post. 
Cc: lgar...@chromium.org js...@chromium.org
Components: UI>Browser>Omnibox UI>Security>UrlFormatting

Comment 3 by ashis...@gmail.com, Apr 15 2017

FYI - I tried same on Edge and Firefox. They do behave slightly differently, more research might be needed there. So exact same example may not work there. Above example as is will only work on chrome, thanks

Ashish Gupta
Owner: mpear...@chromium.org
Thanks for the report. I'm not able to repro this at the moment on M57/M60 on Mac. What version/OS did you use?

I think the critical bit is that if a site could push a URL onto the omnibox's suggestions without any real user-initiated navigation to it. Even without an well-matched IDN-confusible domain, this could lead to an attacker controlled site when the user typed their previously-reliable "f<enter>" prefix.

mpearson -- Can you confirm if it's intentional/correct that omnibox suggestions are influenced by navigations w/o user gestures? In this case it's an iframe, which seems weird to me that it'd influence suggestions.

Comment 5 Deleted

Comment 6 Deleted

Comment 7 by ashis...@gmail.com, Apr 17 2017

I was trying on Version 57.0.2987.133/ Win 10 updated. But had similar results with Mac. To make it easier to reproduce the index.html provided can be called as the "malicious site". I just invoke localhost and frame.htm is what can be returned when intercepting the next 5 injected calls. Also above files were unicode since i was playing with that these ones are better utf8 encoded. One thing to remember is that you will need to proxy/intercept/reply the connection otherwise the "fake" url will not resolve. 
Since its very fast and consistent i uploaded this unlisted video https://youtu.be/sEbVsgaShVI so you can have a look
index.htm
428 bytes View Download
frame.htm
190 bytes View Download
Project Member

Comment 8 by sheriffbot@chromium.org, Apr 17 2017

Status: Assigned (was: Unconfirmed)
Summary: Brief navigations and history API and redirects can be used to add domains to history (was: Security: HSTS Bypass via a "History Poisoning Homoglyph Attack" )
From what I can tell, there is nothing new here compared to using SSLStrip to send users to an ASCII spoof domain like faceb00k.com
There is no bypass of the actual HSTS mechanism.

(Whole-script confusable IDN spoofs are tracked in  Issue 683314 , and near spoofs are tracked in 703750.)

You don't even need the history API to add something the user "didn't visit" (i.e. never had in the URL bar) to their history – a regular redirect will do.

I would WontFix this unless we want to track down all cases in which a domain can be visited briefly (or in the background) without the user noticing they visited the site.
Summary: Brief navigations/history API/redirects can be used to add domains to history (was: Brief navigations and history API and redirects can be used to add domains to history)
It does seem a bit weird that we're scoring these as toplevel visits at all, given that they're subframe navigations, and that we're scoring them as typed visits when they're autogenerated.  Both of those sound suspicious to me.

Comment 12 by ashis...@gmail.com, Apr 17 2017

My idea was to demonstrate the potential of the attack. Whether its due to one issue or multiple thats upto you guys to decide(2 are in the attack) To me any browser auto filling a domain after typing single character with a url that user never visited as shown in video can be abused in very wide variety of scenarios, HSTS bypass is just one of them. Yes HSTS wasnt bypassed from a developer point of view but for a user it effectively was since user is trusting the browser. 

The IDN case i added as i found it highly weird that request was made to a puny code TLD but omnibox showed normal characters. Amazingly firefox behaved similarly, Edge showed puny code in omnibox. If that issue is already tracked then good as i visible url should always match request url imo.
Labels: Security_Severity-Low Security_Impact-Stable OS-All
I'm tentatively triaging this as low severity, though it could also be reasonable to remove the security labels and treat as a possible plain old omnibox bug per comment 11.
Project Member

Comment 14 by sheriffbot@chromium.org, Apr 18 2017

Labels: Pri-2
Cc: mpear...@chromium.org
Owner: ----
Status: Untriaged (was: Assigned)
>>>
mpearson -- Can you confirm if it's intentional/correct that omnibox suggestions are influenced by navigations w/o user gestures? In this case it's an iframe, which seems weird to me that it'd influence suggestions.
>>>
Omnibox suggestions are influenced by anything in your history.  As lgarron@ says, by visiting a page, that page may go through many redirects for example, and all those will be added to the user's history and might show up as suggestions.  I'm a little surprised iframes are having as strong effect as they do here.  Generally though if something can intercept and rewrite all network traffic, I think they'd likely be able to re-train the omnibox to do whatever they want.  I'm not sure if this is a big deal, as if they can intercept all network traffic, they can get the user to see whatever they want to see anyway...

Owner: pkasting@chromium.org
Status: Assigned (was: Untriaged)
From a security perspective, this bug seemed correctly triaged to me, even if perhaps a bit over-cautious (which is good). (I agree with #11 and #13.) pkasting, can you take this or delegate it to a good assignee?
Owner: jdonnelly@chromium.org
-> omnibox TL
Owner: tommycli@chromium.org
Cc: jdonnelly@chromium.org

Comment 20 by ashis...@gmail.com, Apr 21 2017

Hi, Thanks for looking into this, Just wanted to ask in comment#9 it is mentioned that IDN issue is tracked in 683314, i just checked the revision and comment made for it which says "Block a label made entirely of Latin-look-alike Cyrillic letters when the TLD is not an IDN (i.e. this check is ON only for TLDs like 'com', 'net', 'uk', but not applied for IDN TLDs like рф."

i focused entirely on TLD being whole-script IDN confusible for above attack which does not seem like its addressed in that issue. Please have a look and let me know if im wrong. 

Also in comment#15 it is mentioned that "if they can intercept all network traffic, they can get the user to see whatever they want to see anyway". Just wanted to say that an XSS attack can perform the above if the injected site's domain name can be resolved. I chose MITM as i wanted to transparently and automatically proxy any https site and forward user to a similar looking http site. 
Seems like the best fix would be to have Chrome detect and and flag URLs that are homoglyphs of, but aren't actually, Alexa top 1000 sites.
I don't like the idea of special-coding protections to a fixed set of sites.  That seems unfair / limited (why are these sites special) and biased in multiple ways (biased toward sites that are written in a language spoken by more people, biased also toward sites that happen to be in languages/countries wherein Alexa has more penetration).

Lest I be a killjoy, I'll suggest trying to protect a user when the user has two sites in their history that are homoglyphs of each other.  That's the root cause of the problem, and that's the cases we want to protect against, top sites are not.
I think homoglyph-related issues are off-topic for this bug.  If there is action to be taken here, it is covered by comment 11, which applies no matter how widely known the site is or what its URL may look like.  I consider this an omnibox quality issue with a potential extremely-mild security side effect.

There are separate bugs on homoglyph attacks, which cover messaging correctly to the user what site they're on.  If those bugs are addressed, then the security impact of this bug becomes zero.  To avoid confusion, I'm inclined to remove the security tags from this bug now; but I won't go stepping on the security team's toes.

If someone feels the other homoglyph bugs don't cover all possible cases of homoglyphs well enough, the best thing to do would be to file more bugs on those specifically.
mpearson: Hey, yeah, we don't have to hardcode the sites. It could be a component-updater provided list of country specific sites... or the list of sites derived from a user's History or Site Engagement Index. Just wanted to get some general feedback on the idea.

pkasting: Fair enough... I agree that non top level navigations should not appear in the history.
pkasting:

After some investigation, these history entries (both changing the iframe source as well as the history.pushState) are added as PAGE_TRANSITION_MANUAL_SUBFRAME, and indeed can be placed into the inline autocomplete (reproduced with localhost and deleting the competing localhost entries).

I'll start investigating why they are marked as PAGE_TRANSITION_MANUAL_SUBFRAME. It seems that it should be marked as PAGE_TRANSITION_AUTO_SUBFRAME, since there is no user gesture.
Yeah, that seems like half the bug.

The other half is why they're seemingly (from the outcome) scored as typed navs, even if they had a user gesture.
After talking to creis, PAGE_TRANSITION_MANUAL_SUBFRAME is used for any navigation (including history.pushState) that creates a history entry. The name is somewhat confusing because it may or may not have a user gesture.

So that ^ might be a red herring.

I've isolated the bug to somewhere within HistoryQuickProvider, since it doesn't manifest if I remove that provider.

Simplified repro steps:

 1. Visit http://pps-test-a.appspot.com/autocompletebug.html and click on the link.

 2. You will land on http://pps-test-b.appspot.com/frame_test.htm and notice some JavaScript iframe loading.

 3. After that's done, type in the omnibox "pps-test-b". You will notice the inline auto-completion of http://pps-test-b.appspot.com/footest even though you have never typed that address before.
HistoryQuickProvider is pretty naive.  It indexes all pages visited recently, or at least 3 times, or were typed (in all cases as long as they're in the history database, or at least the part we index*).
https://cs.chromium.org/chromium/src/components/history/core/browser/url_database.cc?type=cs&l=640

So if you can manage to get this out of the indexed* history database, that'll do it.

* I'm not sure if this history provider or HistoryURL provider indexes all of the history database or excludes parts of it such as PAGE_TRANSITION_AUTO_SUBFRAME.
I don't think we want it out of the index entirely.  But I think the HQP should probably not be inline-autocompleting something the user has never done an omnibox navigation to, let alone typed.
CL here with before and after screenshots. https://codereview.chromium.org/2846673006/
Screenshot from 2017-04-27 16:57:09.png
104 KB View Download
Screenshot from 2017-04-27 16:58:20.png
101 KB View Download
Per next round of discussions, here's an updated "after" screenshot:


Screenshot from 2017-04-28 15:19:28.png
143 KB View Download
Project Member

Comment 32 by bugdroid1@chromium.org, May 8 2017

The following revision refers to this bug:
  https://chromium.googlesource.com/chromium/src.git/+/121980770b3b9c81971b1277180e303c64905c1c

commit 121980770b3b9c81971b1277180e303c64905c1c
Author: tommycli <tommycli@chromium.org>
Date: Mon May 08 16:51:49 2017

Omnibox: Make InMemoryURLIndex respect hidden URLRows

When HistoryBackend records a new page visit, it creates a new URLRow,
which is marked "hidden" if it has only been visited by subframes.

URLDatabase records these "hidden" URLRows, but explicitly excludes
them from the results of URLDatabase::AutocompleteForPrefix.

InMemoryURLIndex, however, ignores the "hidden" flag. This causes
HistoryQuickProvider to return autocompletions that have never been
visited in the main frame before.

This CL prevents "hidden" URLRows from entering the InMemoryURLIndex's
index. It prevents HistoryQuickProvider from returning completions
that have never been visited in the main frame.

This fix works for both on-the-fly visits, as well as restoring from
on-disk URLDatabase on startup.

One thing to note is that even "hidden" (i.e. subframe) visits are
counted as part of the visit count for URLRows. This seems wrong, since
those visits didn't affect the URL of the Omnibox, and seem more like
internal page state. However, changing that is beyond the scope of this
CL.

BUG= 711772 

Review-Url: https://codereview.chromium.org/2846673006
Cr-Commit-Position: refs/heads/master@{#470019}

[modify] https://crrev.com/121980770b3b9c81971b1277180e303c64905c1c/components/history/core/browser/url_database.cc
[modify] https://crrev.com/121980770b3b9c81971b1277180e303c64905c1c/components/history/core/browser/url_database.h
[modify] https://crrev.com/121980770b3b9c81971b1277180e303c64905c1c/components/omnibox/browser/in_memory_url_index_unittest.cc

Status: Fixed (was: Assigned)
Does "Fixed" mean we don't want to address other kinds of navigations?
Sorry, can you be less concise about what additional issues might remain here?
- Any pages in a redirect chain, esp. the first one.
- Sites redirecting briefly (using e.g. JS/meta refresh) without user interaction, especially when the tab is not in the foreground.
Also, possibly stuffing the navigation history using the history API (can you set different page titles for each of the entries)?
Hey lgarron,

As you mentioned, redirects will still make it into the HQP.

However, redirects will have zero on the "typed" count, and will be ranked lower. https://cs.chromium.org/chromium/src/components/history/core/browser/history_backend.cc?l=769

We have a followup bug here to investigate whether or not HQP should truly return never-typed results: https://bugs.chromium.org/p/chromium/issues/detail?id=719657

I'd like to scope this bug to just the "broken" part, while scoping HQP behavior changes to that 719657 bug. Does that seem reasonable to you?
Sounds reasonable to me!

I don't have any strong opinions, just want to make sure we don't overlook anything.
Project Member

Comment 40 by sheriffbot@chromium.org, May 9 2017

Labels: -Restrict-View-SecurityTeam Restrict-View-SecurityNotify
Status: Assigned (was: Fixed)
tommycli@: To confirm, you don't think the following items are issues outside of the "typed_count == 0 can inline autocomplete" (bug 719657)?
>>>
- Any pages in a redirect chain, esp. the first one.
- Sites redirecting briefly (using e.g. JS/meta refresh) without user interaction, especially when the tab is not in the foreground.
- Also, possibly stuffing the navigation history using the history API (can you set different page titles for each of the entries)?
>>>

I'm concerned about the idea of stuffing visit counts, especially the second or third bullet, which will make the data used to decide when to inline autocomplete buggy.  In other words, making the change suggested by bug 719657 will have a different effects depending on how correct the typed count and visit count data are.  Do you think sites can end up inflating the visit count numbers for an individual URL without user interaction?

Marking this bug as assigned so this question is not overlooked, as I think this is part of the scope of this bug.

mpearson:

Hey, I think the bug ""typed_count == 0 can inline autocomplete" (bug 719657)" covers a whole class of issues, including this one.

I'm treating this particular bug as just limited to the specific report and repro case in c#0, which is focused on an invisible subframe.

In other words, this bug is limited to "Why does HQP provide default autocompletes that HUP rejects?", which has an obvious answer and is just programmer error.

while the new bug is: "Should both HQP and HUP tighten up on typed_count == 0"? -- which is more of a product question we should think through...

I'm not that picky on how we divvy up the issue between the two bugs. If you prefer to consolidate the new bug into this one, I don't have any objection.

Cheers,

Tommy
If you want to consolidate on the other bug, that fine.  I thought this bug was about "Brief navigations/history API/redirects can be used to add domains to history", and was wondering if other forms of navigations and history APIs and redirects can do this, not just the one case you fixed on this bug (things that get marked as "hidden").

Summary: Subframe navigations can be used to add domains to history (was: Brief navigations/history API/redirects can be used to add domains to history)
I updated the title to reflect that it's limited to subframes.

And yeah... history APIs and redirect can also do this... but currently that's by-design, since those URLs do touch the Omnibox (briefly).
Status: Fixed (was: Assigned)

Comment 46 by ashis...@gmail.com, May 19 2017

Hi, may i please know when this issue can be made public? thnx
ashishg1@ - by default security bugs are made public 14 weeks from when they are marked as fixed.
Project Member

Comment 48 by sheriffbot@chromium.org, Aug 17 2017

Labels: -Restrict-View-SecurityNotify allpublic
This bug has been closed for more than 14 weeks. Removing security view restrictions.

For more details visit https://www.chromium.org/issue-tracking/autotriage - Your friendly Sheriffbot

Sign in to add a comment