Issue metadata
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 descriptionVULNERABILITY 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.
,
Apr 15 2017
,
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
,
Apr 16 2017
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.
,
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
,
Apr 17 2017
,
Apr 17 2017
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.
,
Apr 17 2017
,
Apr 17 2017
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.
,
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.
,
Apr 18 2017
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.
,
Apr 18 2017
,
Apr 18 2017
>>> 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...
,
Apr 19 2017
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?
,
Apr 19 2017
-> omnibox TL
,
Apr 20 2017
,
Apr 20 2017
,
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.
,
Apr 25 2017
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.
,
Apr 25 2017
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.
,
Apr 25 2017
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.
,
Apr 25 2017
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.
,
Apr 25 2017
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.
,
Apr 25 2017
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.
,
Apr 27 2017
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.
,
Apr 27 2017
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.
,
Apr 27 2017
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.
,
Apr 28 2017
CL here with before and after screenshots. https://codereview.chromium.org/2846673006/
,
Apr 28 2017
Per next round of discussions, here's an updated "after" screenshot:
,
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
,
May 8 2017
,
May 8 2017
Does "Fixed" mean we don't want to address other kinds of navigations?
,
May 8 2017
Sorry, can you be less concise about what additional issues might remain here?
,
May 8 2017
- 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.
,
May 8 2017
Also, possibly stuffing the navigation history using the history API (can you set different page titles for each of the entries)?
,
May 8 2017
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?
,
May 8 2017
Sounds reasonable to me! I don't have any strong opinions, just want to make sure we don't overlook anything.
,
May 9 2017
,
May 10 2017
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.
,
May 10 2017
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
,
May 10 2017
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").
,
May 10 2017
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).
,
May 10 2017
,
May 19 2017
Hi, may i please know when this issue can be made public? thnx
,
May 19 2017
ashishg1@ - by default security bugs are made public 14 weeks from when they are marked as fixed.
,
Aug 17 2017
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 |
|||||||||||||||||||||||||
Comment 1 by ashis...@gmail.com
, Apr 14 2017