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

Issue metadata

Status: Verified
Owner:
Last visit > 30 days ago
Closed: Apr 2009
Cc:
Components:
EstimatedDays: ----
NextAction: ----
OS: All
Pri: 1
Type: Bug-Security

Restricted
  • Only users with Commit permission may comment.



Sign in to add a comment

ChromeHTML URI handler vulnerability

Reported by roisaltz...@gmail.com, Apr 8 2009 Back to list

Issue description

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.
 
Google Chrome Advisory.doc
147 KB Download
Labels: -Pri-0 -Area-Misc Pri-1 Area-BrowserBackend
Status: Assigned
Thanks for the report.  We've been investigating this issue in another bug.  I'll move the conversation here.
Issue 9838 has been merged into this issue.
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)

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.
Status: FixUnreleased
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.
Spun out javascript / data URL issue as  Issue 9862 .  I'll move this CC list over there.
How do I add roisaltzman to  Issue 9862 ?  The site tells me "Invalid username for owner or CC"  ...
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.
That's super lame.  Have we asked the codesite folks to fix that?
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. 


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=...?
I don't think removing the "return true" is necessary for any known issues.  It's something that might prevent 
some unknown issue.

Comment 13 by lcam...@gmail.com, Apr 8 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
Maybe we should just accept only a single URL after "--" (i.e., apply (3) to all schemes).

Comment 15 by cpu@chromium.org, Apr 8 2009

@lcamtuf : correct. The changes is to compensate for older registrations that dont 
have -- in the cmd line.

@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.


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.

Comment 18 by lcam...@gmail.com, Apr 8 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.
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.


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
------------------------------------------------------------------------

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
------------------------------------------------------------------------

Status: Verified
Verified on build 2.0.172.4 (Official Build 13471), fixed.
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.
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.
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.
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.
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
------------------------------------------------------------------------

Labels: -private
Version 1.0.154.59 has been released with a fix for this issue.
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.


ChromeHTML-Deprecated-Remove.reg
1.2 KB Download
ChromeHTML-Deprecated-Add.reg
1.2 KB Download
Labels: -Area-BrowserBackend Area-Internals
Labels: SecSeverity-High
Labels: Type-Security
Labels: SecImpacts-Stable
Batch update: Guessing based on search criteria that this security bug impacted a stable release.
Project Member

Comment 35 by bugdroid1@chromium.org, Oct 13 2012

Labels: Restrict-AddIssueComment-Commit
This issue has been closed for some time. No one will pay attention to new comments.
If you are seeing this bug or have new data, please click New Issue to start a new bug.
Project Member

Comment 36 by bugdroid1@chromium.org, Mar 10 2013

Labels: -Area-Internals -SecSeverity-High -Type-Security -SecImpacts-Stable Security-Impact-Stable Cr-Internals Security-Severity-High Type-Bug-Security
Project Member

Comment 37 by bugdroid1@chromium.org, Mar 21 2013

Labels: -Security-Severity-High Security_Severity-High
Project Member

Comment 38 by bugdroid1@chromium.org, Mar 21 2013

Labels: -Security-Impact-Stable Security_Impact-Stable
Labels: allpublic
Labels: reward-topanel

Sign in to add a comment