Cross-document script can run in <use> element, through event handlers, when loaded through a same-origin (but cross-document) SVG file
Categories
(Core :: SVG, defect)
Tracking
()
People
(Reporter: johanaxelcarlsson, Unassigned, NeedInfo)
References
Details
(Keywords: reporter-external, Whiteboard: [client-bounty-form])
Attachments
(4 files)
I don't know what to make of this, I tried to search in your issues but did not find anything there.
I found that Firefox implemented a block for iframes in content loaded through <use> tags here https://bugzilla.mozilla.org/show_bug.cgi?id=1754522 . It looks to be specifically to block this as an XSS vector.
However same origin <use> tags can still import JS event handlers. Making the above block useless. From what I have seen this works in Firefox and Webkit but not on Chrome.
SVG file on https://example.com:
<?xml version="1.0"?>
<svg id="x" xmlns="http://www.w3.org/2000/svg">
<image href="1" onerror="alert(1)" />
</svg>
that is loaded like this:
<svg><use href="https://example.com/test.svg#x"/></svg>
will trigger an alert.
It might just be according to specs, but as the iframe fix broke other things in the name of protecting against XSS it looks strange that this still work.
POC:
-
place the two files locally
-
run a webserver
python3 -m http.server 8080
- Visit http://localhost:8080/poc.html in Firefox
| Reporter | ||
Comment 1•1 year ago
|
||
I failed to upload the files. Here is a live example:
https://joaxcar.com/test/tt.html
Updated•1 year ago
|
Comment 2•1 year ago
|
||
Comment 3•1 year ago
|
||
Comment 4•1 year ago
|
||
(Hmm, the testcase doesn't repro the issue in the BMO-hosted version, in part due to how BMO attachments auto-redirect I think.)
I'll attach a zipped up version of the testcase that I confirmed does repro the bug if served from a local http server, so that this can be investigated without relying on the reporter's web server.
Updated•1 year ago
|
Comment 5•1 year ago
|
||
STR with this zipped up testcase:
- Extract locally
- in a terminal, change to the
http-server-contentsdirectory (in this zip file) - Run e.g.
python3 -m http.serverto serve that directory in a local http server - Visit http://localhost:8000/tt.html (assuming your http server is using port
8000)
EXPECTED RESULTS:
No alerts appear.
ACTUAL RESULTS:
An alert appears saying 1.
Firefox/Epiphany (WebKit) give ACTUAL RESULTS.
Chrome gives EXPECTED RESULTS.
Comment 6•1 year ago
•
|
||
This is probably not super-concerning from a security perspective -- the referenced bug (bug 1754522) ended up being viewed more as a compat issue than as a sec issue, per bug 1754522 comment 19 and surrounding comments (e.g. bug 1754522 comment 23 where emilio and the reporter seem to note that Firefox at-that-time was technically matching the spec.
Here, as with bug 1754522, I think our behavior (which in this case matches at least one other browser) is also correct per-spec....
Script elements are blocked due to this note in the spec:
Within a use-element shadow tree, ‘script’ elements are inert (do not execute).
https://svgwg.org/svg2-draft/struct.html#UseElement
...and that's why we blocked iframe elements as well in bug 1754522. That wouldn't automatically imply that event handlers like onerror, onclick, etc. should be blocked, though. (Though I do see the logic in expecting that they might be blocked.)
In fact, the spec has a whole section on how event handlers should work in <use> shadow trees (implying that they should work):
https://svgwg.org/svg2-draft/struct.html#UseEventHandling
So at first glance, I think that spec section requires onerror (and onclick, etc) to work in a use shadow-tree, in the way that it currently does in WebKit/Gecko, unless I'm missing something...
Comment 7•1 year ago
|
||
Yeah, also I don't think we limit <iframe> for same-origin use cases? That's what svg.use-element.graphics-element-restrictions controls right now.
I think this probably shouldn't be hidden (and probably shouldn't be considered XSS since it's same-origin only? Or am I missing something?) If it works cross-origin then it could have some impact I guess (though still unclear how much as per the other bug)
Comment 8•1 year ago
•
|
||
(In reply to Emilio Cobos Álvarez (:emilio) from comment #7)
Yeah, also I don't think we limit
<iframe>for same-origin use cases? That's whatsvg.use-element.graphics-element-restrictionscontrols right now.
That pref seems to relate to same-vs-cross document use cases, not same-vs-cross origin. (In particular: we do limit <iframe> for same-origin-but-cross-document use-cases, depending on the value of that pref; see B vs. B' in my next comment.)
But setting that aside: on the broader point, I agree with you: this shouldn't be considered XSS since these scripts only run when everything is same-origin. I tested with a cross-origin SVG file (two different http servers running on different ports) and got an error like this in my error console:
Security Error: Content at http://localhost:8000/test-separatedoc-xor.html may not load data from http://localhost:8001/resource.svg.
...and the <use>-clone failed entirely (nothing from it renders or fires event handlers), as expected.
Comment 9•1 year ago
|
||
Here's a testcase that I used locally to prod at this a bit more. In this testcase, everything is same-document.
For content inside the <use>-cloned subtree, the presence of redundant-looking log message is an indication that the <use>-cloned version was able to run scripts.
In this same-document example:
A. <script> elements: Gecko, WebKit, Chromium agree they do not get run in the <use> clone
B. <iframe> elements: Gecko honors/runs them in the <use> clone; WebKit/Chromium do not. (Gecko with svg.use-element.graphics-element-restrictions = 2 behaves like WebKit/Chromium, matching the documentation for the pref)
C. event handlers (onload, onclick, onerror): Gecko, WebKit, Chromium agree that they do get run in the <use> clone.
If I change this testcase to move the <use>-targeted resource to a separate (but same-origin) SVG document (note that this means the first copy of each category of log message no longer runs because the svg resource doc itself isn't part of the main document), then I get the following results:
A'. <script> elements: as above, they don't get run in any browser.
B'. <iframe> elements: still not honored in WebKit/Chromium; also no longer honored in Gecko, unless I relax svg.use-element.graphics-element-restrictions = 0 per that pref's documentation.
C'. event handlers: Chromium now decides that they do not get run. Gecko/WebKit still run them.
So C vs. C' is the relevant difference here. Chromium makes a distinction between same-doc vs. cross-doc for event handlers, which they do not make for other categories of scripts (script and iframe). I don't know why they do that.
Comment 10•1 year ago
|
||
Seems like a Chrome bug. I also don't see a Firefox bug here.
Comment 12•1 year ago
|
||
Comment on attachment 9418837 [details]
testcase 1
(now that this is un-hidden, testcase 1 actually works to demonstrate Firefox's behavior, since BMO's extra magic token args on secure bug attachments are no longer a factor.)
Updated•1 year ago
|
| Reporter | ||
Comment 13•1 year ago
|
||
Thanks for looking into this and the deep dive into how this should/does work!
I agree that this is probably the most spec-compliant implementation.
I would say (without knowing the details) that Chrome blocks these event handlers to prevent this situation:
- A site allows for file uploads and protects itself from XSS by adding a
content-disposition: attachmentto theSVGfiles. - The same site allows for some restricted user-controlled HTML but uses some form of sanitization for XSS. This sanitization does not include
usetags (see the Salesforce example in the issue with iframes)
This scenario leads to XSS on Firefox and Safari but not in Chrome. But I believe you are right that Chrome is breaking the specs here, in the name of security.
Thanks again, I learned a lot!
/Johan
Comment 14•1 year ago
|
||
Thanks. Closing as INVALID for now, since I don't think we intend to change behavior here.
(We could in theory extend the svg.use-element.graphics-element-restrictions:1 configuration to match Chrome on this, but it's not clear that that's adding much in the way of robust protections, or that Chrome's behavior is specced or intentional).
(In reply to johanaxelcarlsson from comment #13)
I would say (without knowing the details) that Chrome blocks these event handlers to prevent this situation:
That's possible, though it could also just be an inadvertent bug on Chrome's end. :) For what it's worth, I tested some old Chrome versions and found that:
- Chrome 71 (and earlier) match Firefox/Safari on testcase 1, showing the alert(1)
- Chrome 72 (and newer) match current Chrome on testcase 1, and do not show any alert.
I don't see anything in the Chrome 72 release notes that would correspond to this change (though of course they're incomplete, but they tend to highlight security-relevant changes and known-breaking-changes). So that lends a little bit of credibility to Chrome's behavior here being inadvertent rather than an intentional defense mechanism (particularly given that it's inconsistent per last sentence in comment 9)
This scenario leads to XSS on Firefox and Safari but not in Chrome. But I believe you are right that Chrome is breaking the specs here, in the name of security.
Again, "XSS" isn't quite the right word here, since nothing happens at all here unless the content is all hosted same-origin. The setup you're describing has multiple bits of untrusted user-provided content, hosted on an origin that's got data that's meant to be protected from those untrusted users; that hypothetical setup is arguably the problem in that scenario, rather than SVG <use> restrictions being insufficient.
(Having said that: the web is messy, and I'm sure there are folks doing what you're describing.)
Comment 15•1 year ago
|
||
Johan, it would be really interesting if you could find what triggered this change in Chrome. I tried going through the release notes, their whole changelog (terrible slow big HTML file. I also looked at the json format), but I could not find anything relevant. Maybe you'll find some supporting evidence why this should be fixed?
I am also CCing Leo Balter, as I presume he might have some additional insights into site-specific behavior.
Updated•1 year ago
|
Description
•