Open Bug 1049873 Opened 10 years ago Updated 2 years ago

Scripting is enabled in <use>-cloned content from resource documents (<embed>/<iframe>/<object> tags in particular)

Categories

(Core :: SVG, defect)

defect

Tracking

()

UNCONFIRMED

People

(Reporter: longsonr, Unassigned)

Details

Attachments

(5 files, 1 obsolete file)

      No description provided.
Attached image resource document
Attached image testcase (obsolete) —
Attached image testcase
Attachment #8468747 - Attachment is obsolete: true
Seems the testcase doesn't work in bugzilla. Download the files and either run it locally or within an http server (could be https stops it).

To run locally don't forget to fix up the testcase's use xlink:href to point to the resource document.
Version: unspecified → Trunk
Expected results nothing.

Actual results the embed javascript runs (but the svg javascript does not).
I can reproduce, with local copies of the testcases (w/ path fixed up per comment 4), both when viewing the file directly and when viewing the file over HTTP using "python -m SimpleHTTPServer".

The alert comes from this chunk, inside of the resource document:
>    <foreignObject>
>        <embed xmlns="http://www.w3.org/1999/xhtml" src="javascript:alert('embed')"/>
>    </foreignObject>
Summary: Scripting should be disabled in resource documents → Scripting should be disabled in resource documents (including disabling javascript URIs in <embed> tags)
You can replace embed by iframe, or embed by object (providing you also substitute data for the src attribute) and you get the same issue.
Summary: Scripting should be disabled in resource documents (including disabling javascript URIs in <embed> tags) → Scripting should be disabled in resource documents (including disabling javascript URIs in <embed>/<iframe>/<object> tags)
Hmm.  I guess the point is scripting is implicitly disabled for the resource document itself by virtue of not having a window, but iframes create their own windows...  I'm not sure why the <embed> thing works, though, since I'd think that would run against the parent window.
Flags: needinfo?(bzbarsky)
How bad of a security issue is this?  Is this like sec-high or something?
Flags: needinfo?(dholbert)
Could this trick be used to run scripts in an <img> svg?
If so what would the origin of the scripts be?
Could this be used to run javascript in a docshell with JS disabled (e.g. thunderbird, NoScript)?
Not in an <img> as far as I can tell from my testing. 

resource files must be same domain for <use> rendering to work but I haven't tested whether they must be same domain for this scripting trick to work.

javascript must be enabled.
Using the test files, it does appear that Fx is the only affected browser. Does not occur on Safari/Chrome/IE.
(In reply to Boriz Zbarsky [:bz] from comment #9)
> I'm not sure why the <embed> thing works, though, since I'd
> think that would run against the parent window.

I think it does, and the parent window is the window of the host document, since this content is cloned (via '<use>') into the host document.
Specifically, we get a call to HTMLSharedObjectElement::BindToTree with aDocument being the host document and with 'this' being an <embed> element.  This is a clone of the resource doc's <embed>, generated via :SVGUseElement::CreateAnonymousContent.

HTMLSharedObjectElement::BindToTree queues up a script runner to load the <embed>'s src URI (which is a javascript URI in this case), which runs with the principal of the <embed>'s document (which is the host document). So, it works just like <embed> in the host document would.
So FWIW, this chunk of the resource doc...
 <script>alert("svg")</script>
...doesn't execute when cloned into the host document, but it's not directly because of any security restrictions.

It's just because that cloned nsScriptElement has "mAlreadyStarted" set to true, since it's a clone, and that flag gets copied when it's cloned from the original <script> element in the resource-doc, here:
http://mxr.mozilla.org/mozilla-central/source/content/svg/content/src/SVGScriptElement.cpp?rev=afcb3af79d09&mark=70-71#57

But if that bool were false (e.g. if I force it to false in GDB when we get here with the cloned node), then we'll go right ahead and execute that alert() when the cloned <script> is bound to the host document, in nsScriptElement::MaybeProcessScript().
Flags: needinfo?(dholbert)
Attachment #8475559 - Attachment description: testcase that works on bugzilla directly (uses scripting powers to redirect to youtube) → testcase 2 (uses scripting powers to redirect to youtube)
(In reply to Daniel Veditz [:dveditz] from comment #11)
> Could this trick be used to run scripts in an <img> svg?
[...]
> Could this be used to run javascript in a docshell with JS disabled

No and no. It lets <embed> nodes cloned by <use> run script, *if* those nodes would've been allowed to run script if they were directly in the host document.

In an image or in a JS-disabled docshell, the <embed> nodes can't run script, and this trick doesn't help them do that.
Here's a testcase that doesn't bother with "javascript:" URI, and instead just directly has an <iframe> which is cloned & rendered (and has its own javascript dutifully run).

I don't have a strong sense for whether or not any of this is a security risk yet.
Ah, this is specific to <use>; I should have read the testcases.  That makes sense.

So what should happen if the <use> targets a <rect onmousemove="alert('heya')">.  Should the alert happen when clicked?  I see alerts in Gecko and Safari and Chrome (the latter over http://, since over file:// their same-origin policy disallows the <use> entirely).  And I seem to recall the spec requiring this behavior.

So it seems to me like in practical terms if you <use> something from an untrusted document you lose in terms of it being able to run script in your global...  The important part for our purposes is it happens in a window global, which is a normal thing to do.  Combined with the fact that we only allow same-origin <use>, I'm not sure there's a security hole here.

Looks like WebKit actually explicitly disallows <use> if the target contains a foreignObject.  See https://github.com/WebKit/webkit/commit/53d1d1305ab417315626a45509f98d7814571756 and the tests it added.  That code is still in the tree; as of today, https://github.com/WebKit/webkit/blob/923b23fd3c25424244e5add6f392844926a92b87/Source/WebCore/svg/SVGUseElement.cpp#L333 shows the things that they disallow in the subtree <use> targets.
Flags: needinfo?(bzbarsky)
Summary: Scripting should be disabled in resource documents (including disabling javascript URIs in <embed>/<iframe>/<object> tags) → Scripting is enabled in <use>-cloned content (<embed>/<iframe>/<object> tags in particular)
Summary: Scripting is enabled in <use>-cloned content (<embed>/<iframe>/<object> tags in particular) → Scripting is enabled in <use>-cloned content from resource documents (<embed>/<iframe>/<object> tags in particular)
Do we want to follow webkit and disallow foreignObject in <use>? Or just consider this expected behavior and not a security bug?
More likely the latter I expect. Do you think this is really something we need worry about roc? We're protected by same domain for <use>
Flags: needinfo?(roc)
I can't think of any reason to consider this a security bug.
Flags: needinfo?(roc)
I'm going to ask the SVG WG what functionality we should have here.
Group: core-security
Status: NEW → UNCONFIRMED
Ever confirmed: false
Severity: normal → S3
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: