| Issue 9860: | ChromeHTML URI handler vulnerability | |
| 3 people starred this issue and may be notified of changes. | Back to list |
Sign in to add a comment
|
A vulnerability in the ChromeHTML URI handler allows an attacker to bypass the Same Origin Policy for any site and also enumerate victims files and directories. When loaded in Internet Explorer, a specially crafted HTML page can launch Google Chrome with an arbitrary URI without requiring any user interaction. A more detailed and technical security advisory explaining the issues is attached. |
||||||||||||||||||
,
Apr 08, 2009
Thanks for the report. We've been investigating this issue in another bug. I'll move the conversation here.
Status: Assigned
Owner: c...@chromium.org Cc: aba...@chromium.org Labels: -Pri-0 -Area-Misc Pri-1 Area-BrowserBackend |
|||||||||||||||||||
,
Apr 08, 2009
Issue 9838 has been merged into this issue.
Cc: de...@chromium.org i...@chromium.org skyli...@chromium.org secur...@chromium.org
|
|||||||||||||||||||
,
Apr 08, 2009
Reported by lcamtuf, Yesterday (18 hours ago) Hi all, We received this report from an external researcher Roi Saltzman (of IBM / Watchfire) via security@google.com. So far, we were unsuccessful in asking him to file it here directly. If he does, please dupe this bug against his, rather than the other way round. Also, if the report is confirmed, please do not push out & announce fixes without checking with the reporter first. Detailed advisory (Google Chrome Advisory.doc) is attached as-is. If I am reading this correctly, the claim is that: 1) Because of a known silliness of MSIE, calls to registered URL handlers for protocols such as chromehtml: are not constructed with sufficient escaping. We previously combated cases where this could be used to pass unsolicited --no-sandbox or --renderer-path to the browser. In this variant, the author also notes that unescaped spaces & quotes might be used to break one parameter into several, and this would cause Chrome to open multiple tabs - the first one for the actual chromehtml:, and additional ones for unconstrained protocols such as javascript: or file:. If so, this by itself should not be a huge security problem, although it would for example permit file:/// trickery. The most obvious workaround is to reject or concatenate multiple parameters if chromehtml: is detected in the first one. 2) The other claim is that if javascript: URLs are passed this way, they apparently execute with additional "chrome" privileges that let them register a timer and have it survive a page transition through "document.location.assign()" (which, I presume, has the same effect as location.assign()), resulting in attacker-controlled code executing in an arbitrary domain. I could not reproduce this with Chrome 2.0, but the report is for 1.0, and I do recall some discussions of security improvements for bookmarklets and other javascript on chrome-ui: pages and the like - perhaps related. /mz Comment 1 by ian@chromium.org, Yesterday (18 hours ago) Additional comment from Will: I was able to reproduce this using IE7 and Chrome 1.0.154.53 by visiting the following link in IE7 with Chrome closed: http://static.dataspill.org/b3f8cd893eab9fabe99d642a10da7f31ae4ddc23/poc.html I could not reproduce with 2.0.169.1 assigning to cpu@ [Comments 2 and 3 omitted. They're some emails we exchanged with the reporter.] Comment 4 by cpu@chromium.org, Yesterday (17 hours ago) I'll look into #1. This is an obvious bug to spot, if we ever tested. grrrr. Talking to Adam about #2 Comment 5 by lcamtuf, Yesterday (17 hours ago) Yeah, but #1 by itself wouldn't be much of a deal :-( Comment 6 by abarth@chromium.org, Yesterday (17 hours ago) The same-origin bypass is cute. We don't have a "chrome" security context like Firefox. The exploit makes use of the "isSecureTransitionTo" logic (e.g., http://trac.webkit.org/browser/trunk/WebCore/loader/FrameLoader.cpp#L929 ) to move the malicious script from the initial about:blank document to a Web document. We allow this to support scripts like: var win = window.open("http://www.google.com/"); win.foo = 42; which don't expect "foo" to be blown away when http://www.google.com/ is (asynchronously) loaded into the frame. Our behavior seems to have changed between 1.0 and 2.0. In 1.0, timeouts survive these transitions. In 2.0, the timeouts get canceled. However, modifications to the global object still persist across these navigations. That means you can UXSS, but the exploit is more subtle. The correct fix for this part of the issue is to disallow crazy URLs from the command line. We should allow only "Web-safe" schemes (as defined by RendererSecurityPolicy ::IsWebSafeScheme) and file:// URLs. Comment 7 by lcamtuf, Yesterday (17 hours ago) Permitting: var win = window.open("http://www.google.com/"); win.foo = 42; ...seems crazy and dangerous to me if 'foo' then survives page transition and appears in google.com context, no? One example would be injecting faux win.postMessage across domains, and having www.google.com think it's a legit one in a browser that does not support it natively, then calling it. Does any other browser permit something of this nature? /mz Comment 8 by lcamtuf, Yesterday (17 hours ago) Does not seem to be something that Firefox permits; what would be a legitimate usage scenario for anything like this? Comment 9 by abarth@chromium.org, Yesterday (17 hours ago) > seems crazy and dangerous to me Yeah. Sorry if I wasn't clear. This only works if everything is same-origin. :) See SecurityOrigin::isSecureTransitionTo at http://trac.webkit.org/browser/trunk/WebCore/page/SecurityOrigin.cpp#L199 The key thing this exploit makes use of is the special "return true" on http://trac.webkit.org/browser/trunk/WebCore/page/SecurityOrigin.cpp#L203 It's possible we could remove that line, but I'm not sure what the consequences would be. We should block weird schemes on the command line regardless. > Does any other browser permit something of this nature? I think they all do. This idiom is very common. I think most Web developers don't realize that http://www.google.com/ loads asynchronously. Comment 10 by abarth@chromium.org, Yesterday (17 hours ago) > Does not seem to be something that Firefox permits Really? /me goes to test. Comment 11 by abarth@chromium.org, Yesterday (17 hours ago) Seems to work for me: http://webblaze.org/abarth/tests/secure-transition/ Comment 12 by abarth@chromium.org, Yesterday (17 hours ago) Even works in IE8. :) Comment 13 by lcamtuf, Today (16 hours ago) I agree on fixing #1, but it still seems dangerous. I am not particularly familiar with this code, but I can probably get my Internet-originating Javascript running in a context that satisfies isEmpty() - e.g., create a blank IFRAME, then access its DOM (since it inherits my SOP context) and put a timer there, have the timer fire, call createElement to create a new IFRAME and append it to its own document.*, then point this IFRAME to www.google.com and inject postMessage or any other method / property that the code might be using blindly under the assumption that its context would not be tainted (?). Comment 14 by lcamtuf, Today (16 hours ago) Oh yeah, but your test is same-origin; I'm talking about blank -> non-SOP target special case. If navigation target SOP context is consistent with SOP context of the owner of the navigated frame, I think this has no security consequences. Delete comment Comment 15 by abarth@chromium.org, Today (16 hours ago) I tried to break this for a while a number of months ago, but I couldn't find a way. The following invariant seems to hold: securityOrigin()->isEmpty() IFF JavaScript environment is empty Notice that a Web origin will never be able to access an empty security Origin because canAccess will return false (because "http" != ""). In this case, the invariant breaks down because the javascript URL on the command line gets run when securityOrigin()->isEmpty(). Now that I'm thinking about this again, I think we should be able to remove that return statement. Why should we preserve modifications to the JavaScript environment if there can't possibly be any? I'll work with upstream to see if we can do this too. Comment 15 by abarth@chromium.org, Today (16 hours ago) I tried to break this for a while a number of months ago, but I couldn't find a way. The following invariant seems to hold: securityOrigin()->isEmpty() IFF JavaScript environment is empty Notice that a Web origin will never be able to access an empty security Origin because canAccess will return false (because "http" != ""). In this case, the invariant breaks down because the javascript URL on the command line gets run when securityOrigin()->isEmpty(). Now that I'm thinking about this again, I think we should be able to remove that return statement. Why should we preserve modifications to the JavaScript environment if there can't possibly be any? I'll work with upstream to see if we can do this too. Comment 16 by lcamtuf, Today (16 hours ago) I just tried a couple of obvious tricks and yup, this seems to be consistent with your findings; although note that it is possible to lose a http:// SOP context by opening a data:text/html,<script>...</script> window (creator will not have direct access to what's inside, but obviously gets to put any code in there at creation time). So I am somewhat concerned. Comment 17 by skylined@chromium.org, Today (106 minutes ago) Based on that, here is a PoC that opens a page in Chrome with a TEXTAREA in which you can type JavaScript, which gets executed when you double click on the TEXTAREA. Useful for playing around: <html> <script> var html = '<TEXTAREA%2520style=width:100%2525;height:100%2525%2520id=xss%2520ondblclick=eval(do cument.getElementById(\'xss\').value)></TEXTAREA>'; document.location = 'chromehtml:"80 data:text/html,' + html </script> </html> Notice how DOUBLE encoding is needed. Besides universal XSS and detecting local files, I can't think of anything that an attack could do with this, even taking into account other protocols, such as ftp. The reporter opened a bug: http://code.google.com/p/chromium/issues/detail?id=9860 Shall we continue our conversation there or close that bug and point here (in which case the reporter does not have access to the bug) |
|||||||||||||||||||
,
Apr 08, 2009
As part of http://code.google.com/p/chromium/issues/detail?id=5825, we have committed changes to the "ChromeHTML:" protocol handler: - We're removing it as a protocol handler from the registry: http://codereview.chromium.org/21477 - We're checking if we're being invoked through an outdated "chromehtml:" protocol handler registry entry: http://codereview.chromium.org/20469 With these changes, we either remove the attack vector by removing the registry key or (should that fail for some reason such as elevation on Vista) we no longer load anything passed to us using the outdated registry entry. That should take care of the attack vector. That still leaves the (now theoretical) problem of "javascript:" and "data:" urls opened from the command-line having XSS access. |
|||||||||||||||||||
,
Apr 08, 2009
skylined, can you add the SVN revision numbers to this bug? (Maybe the bugdroid will do that?) Let's handle the javascript / data URL stuff in another bug.
Status: FixUnreleased
|
|||||||||||||||||||
,
Apr 08, 2009
Spun out javascript / data URL issue as Issue 9862. I'll move this CC list over there. |
|||||||||||||||||||
,
Apr 08, 2009
How do I add roisaltzman to Issue 9862? The site tells me "Invalid username for owner or CC" ... |
|||||||||||||||||||
,
Apr 08, 2009
You can't CC someone who's not a project member. They can star the bug and then they will get email updates (but not if it's private). C'est la vie. |
|||||||||||||||||||
,
Apr 08, 2009
That's super lame. Have we asked the codesite folks to fix that? |
|||||||||||||||||||
,
Apr 08, 2009
I will merge the fixes for issue 5825 to the 154 release branch. There will be a release next week that includes the fix for this. |
|||||||||||||||||||
,
Apr 08, 2009
So to be clear, so far we're talking about - disabling crazy schemes from command line in 9862 - pushing the two fixes from 5825 And those two together fix all the known problems for 1.0 and 2.0? Do we need to remove the "return true" mentioned above to prevent any other crazy var x = window.open, x.foo=...? |
|||||||||||||||||||
,
Apr 08, 2009
I don't think removing the "return true" is necessary for any known issues. It's something that might prevent some unknown issue. |
|||||||||||||||||||
,
Apr 08, 2009
Unless I am mistaken, the latter fix in 5825 (http://codereview.chromium.org/20469) does not prevent chromehtml: argv splitting, but merely, stops parameter injection (by requiring -- to be present first if chromehtml: is found). So in the scenario where it matters (where we are unable to nuke / update chromehtml: registry keys), it would still not prevent javascript: or file: from being passed by injecting unescaped quotes / whitespaces in the URL. If other planned fixed disable javascript: calling from cmdline, it would mitigate the attack, but it's still conceptually bad to allow file:/// URLs to be opened by http content (mostly because there is a risk of cross-talk with other browsers, MUAs, etc, that store downloaded files at predictable locations, which would then permit http -> file promotion). A good way to further compensate for this would be any of the following: 1) Bailing out with an error if chromehtml: is spotted in cmdline, but more than one URL seems to be passed, 2) Ignoring any subsequent URLs after chromehtml: from cmdline, 3) (Most correct) Concatenating any argv that follow chromehtml: into a single URL and opening it instead. /mz |
|||||||||||||||||||
,
Apr 08, 2009
Maybe we should just accept only a single URL after "--" (i.e., apply (3) to all schemes). |
|||||||||||||||||||
,
Apr 08, 2009
@lcamtuf : correct. The changes is to compensate for older registrations that dont have -- in the cmd line. |
|||||||||||||||||||
,
Apr 08, 2009
@lcamtuf: Here's how I understand it: http://codereview.chromium.org/20469 prevents Chrome from doing anything if it finds that it is being invoked through the old (bad) registry entries: ChromeMain returns 1 and Chrome terminates. So in case we cannot change the registry, Chrome can still be started, but it terminates immediately and does not open anything. This should stop any exploit from being able to inject anything. http://codereview.chromium.org/21477 changes the registry to remove the ability to start Chrome through "ChromeHTML:" protocol handlers altogether. Now that I think about it, it makes more sense to just check for 'chromehtml:' in the arguments, rather than check if it is preceded by '--' to determine if Chrome is being invoked through an old registry entry: we're removing the registry entry that allows execution through chromehtml in the first place so we should NEVER find chromehtml: in the arguments, no matter what. I think that may be an artifact from when we were not planning to remove it but change it, so I'll ask around. |
|||||||||||||||||||
,
Apr 08, 2009
PS. I use the ability to open multiple pages in Chrome through the command-line; I don't think we should remove a perfectly good feature because we failed to get some other feature right the first time. |
|||||||||||||||||||
,
Apr 08, 2009
skylined, the scenario is: 1) We have a correct chromehtml: handler with -- registered (so 20469 check passes), 2) We can't nuke it for whatever reason, because we no longer have the permissions we had back then (so 21477 does nothing), 3) An URL of 'chromehtml:blarg" "javascript:do_evil_stuff' is encountered, and Chrome is called from MSIE as: chrome -- "chromehtml:blarg" "javascript:do_evil_stuff" (Substitute that for file:/// when we block javascript:) 4) The result is not desirable unless we further detect and compensate for this parameter splitting. |
|||||||||||||||||||
,
Apr 08, 2009
Okay, I understand what you're worried about. I was working under the assumption that everybody had a "broken" (without '--') "chromehtml:" handler. I've asked the people that worked on the original '--' fix if we can terminate chrome as soon as we encounter "chromehtml:", rather than just when we encounter it without a '--' prefix. AFAIK we do not want to be loaded through "chromehtml" at all anymore, so we should not allow it in any way. That should fix the scenario you describe by taking away all means to open anything in Chrome from MSIE, even if the registry entry is still there in any form. |
|||||||||||||||||||
,
Apr 08, 2009
Here is the fix : http://src.chromium.org/viewvc/chrome?view=rev&revision=13384 |
|||||||||||||||||||
,
Apr 08, 2009
The following revision refers to this bug:
http://src.chromium.org/viewvc/chrome?view=rev&revision=13384
------------------------------------------------------------------------
r13384 | cpu@google.com | 2009-04-08 15:03:41 -0700 (Wed, 08 Apr 2009) | 9 lines
Changed paths:
M http://src.chromium.org/viewvc/chrome/trunk/src/chrome/app/chrome_dll_main.cc?r1=13384&r2=13383
Fix for invocation over deprecated protocol handler
- We don't support chromehtml protocol anymore and future installers do not register it
- Avoid stale registry entries to invoke us
BUG=9860
BUG=9862
Review URL: http://codereview.chromium.org/64003
------------------------------------------------------------------------
|
|||||||||||||||||||
,
Apr 09, 2009
The following revision refers to this bug:
http://src.chromium.org/viewvc/chrome?view=rev&revision=13470
------------------------------------------------------------------------
r13470 | laforge@chromium.org | 2009-04-09 15:15:10 -0700 (Thu, 09 Apr 2009) | 11 lines
Changed paths:
M http://src.chromium.org/viewvc/chrome/branches/172/src/chrome/app/chrome_dll_main.cc?r1=13470&r2=13469
Merge 13384 - Fix for invocation over deprecated protocol handler
- We don't support chromehtml protocol anymore and future installers do not register it
- Avoid stale registry entries to invoke us
BUG=9860
BUG=9862
Review URL: http://codereview.chromium.org/64003
TBR=cpu@chromium.org
Review URL: http://codereview.chromium.org/67020
------------------------------------------------------------------------
|
|||||||||||||||||||
,
Apr 10, 2009
Verified on build 2.0.172.4 (Official Build 13471), fixed.
Status: Verified
|
|||||||||||||||||||
,
Apr 14, 2009
Hi Folks, Thanks for your quick response and fixes. If I understand correctly, the proposed fix does mitigate the issues I had brought up. I'd be happy to be able to read up the second bug issue (9862). Abrath mentioned that he couldn't add me to the issue and indeed, I get a 403 Forbidden when accessing the page. Will merge 13384 be released as an update? If so, could you say when? Any question are welcome, Roi. |
|||||||||||||||||||
,
Apr 14, 2009
Hi Roi, Issues 9862, which should prevent Chrome from launching a data:, javasript: or other "unsafe" url from the command line is still being worked on. Once we have something, I'll let you know. Mal should be able to answer the question about release dates. |
|||||||||||||||||||
,
Apr 14, 2009
We plan to release the fix on the 22d of April to the Stable channel (majority of users). The fix will be in a Beta channel update this week, but we won't disclose the fix until next week when we can update everyone. |
|||||||||||||||||||
,
Apr 16, 2009
Skylined & mal - thanks. After the fix for this will be released I would like to blog about it. You should note that while the blog post mainly contains technical information, we would be sure to emphasize that Google Chrome team has been very responsive and is committed to the security and protection of their end users. Again, as per our vulnerability disclosure policy, we will not release any information on this vulnerability until the fix will be released. |
|||||||||||||||||||
,
Apr 17, 2009
The following revision refers to this bug:
http://src.chromium.org/viewvc/chrome?view=rev&revision=13998
------------------------------------------------------------------------
r13998 | mal@chromium.org | 2009-04-17 21:22:20 -0700 (Fri, 17 Apr 2009) | 7 lines
Changed paths:
M http://src.chromium.org/viewvc/chrome/branches/release_154.next/src/chrome/app/chrome_dll_main.cc?r1=13998&r2=13997
Merge r13384 to the 154 branch.
Fix for invocation over deprecated protocol handler
BUG= 9860
TBR= cpu
Review URL: http://codereview.chromium.org/79077
------------------------------------------------------------------------
|
|||||||||||||||||||
,
Apr 23, 2009
Version 1.0.154.59 has been released with a fix for this issue.
Labels: -private
|
|||||||||||||||||||
,
Apr 24, 2009
I'm behind a proxy/firewall which blocks me from getting updates. I installed Chrome using the standalone version. While I download the updated version, I removed the registry keys which enable IE to work its magic. If you're in a similar situation, download and merge (double-click) the "Remove" reg key. The Add will put it back, if for some reason you want to do that. The behavior is deprecated, and in fact these keys are not added in new installations of chrome. Of course, if at all possible, you should download the available google patches. I'll be doing that tonight and bring in the updates manually. |
|||||||||||||||||||
|
|
|||||||||||||||||||