HTML Sanitizer Bypass with combined Image + onerror and STYLE element
Categories
(Core :: DOM: Core & HTML, defect, P1)
Tracking
()
People
(Reporter: sourc7, Unassigned)
References
Details
(Keywords: reporter-external, sec-high, Whiteboard: [reporter-external] [client-bounty-form] [verif?])
Attachments
(3 files)
When directly testing the HTML Sanitizer, I found I able to bypass Firefox 83.0a1 (2020-09-23) HTML sanitizer with mXSS payload: <svg><style>[any xss payload]
In example after inserting document.body.innerHTML = '<svg><style><svg onload="javascript:alert(1337)"></svg>'
to the browser console, I didn't receive warning message from the HTML sanitizer (e.g. "Removed unsafe attribute. Element: svg. Attribute: onload.").
Comment 1•4 years ago
|
||
The resulting parsed DOM is <svg><style></style></svg>
though, so it's not clear to me whether there's really an issue here - maybe we're neglecting to warn because ? Kris or Freddy, do you know?
Reporter | ||
Comment 2•4 years ago
|
||
The resulting parsed DOM is <svg><style></style></svg> though
Hi :Gijs what command to show the DOM output? I'm sorry if this is a false positive.
I'm currently using Firefox DOMParser the output is:
var payload = `<svg><style><svg onload="javascript:alert(1337)"></svg>`;
var doc = new DOMParser().parseFromString(payload, "text/html")
doc.body.innerHTML
"<svg><style><svg onload=\"javascript:alert(1337)\"></svg></style></svg>"
Reporter | ||
Comment 3•4 years ago
|
||
Comment 4•4 years ago
|
||
Well, I'm pretty sure it's not warning about the onload
attribute because the entire <svg> element is being dropped. As for why the SVG element is being dropped, I have no idea. It would be interesting to know, but as long as we're not actually executing the script, I'm happy.
Comment 5•4 years ago
|
||
(In reply to Irvan Kurniawan from comment #2)
The resulting parsed DOM is <svg><style></style></svg> though
Hi :Gijs what command to show the DOM output? I'm sorry if this is a false positive.
I used .innerHTML
in the about:config
document, as you did in comment #0. Although the assignment expression's result is the same as the input (ie so that foo = bar = "string"
assigns the same string everywhere), if you check document.body.innerHTML
after the assignment, you'll see that the attribute has disappeared.
I don't know if it's a false positive, I'm not an expert on our sanitizer code. The blogpost does suggest using innerHTML
.
I'm currently using Firefox DOMParser the output is:
var payload = `<svg><style><svg onload="javascript:alert(1337)"></svg>`; var doc = new DOMParser().parseFromString(payload, "text/html") doc.body.innerHTML "<svg><style><svg onload=\"javascript:alert(1337)\"></svg></style></svg>"
If you check doc.nodePrincipal
after this snippet (assuming you're executing in a privileged console) then you'll see it's a null principal (ie same as a sandboxed iframe) - the DOM parser is parsing into a new, unprivileged document. Therefore the sanitizer does not run (or it'd break web content using innerHTML unsafely - of course that might be a good thing for security, but users can't really deal with that level of breakage...). You can compare with document.nodePrincipal
which on about:config or about:preferences or similar will show a system principal ("chrome privileges", ie same execution privileges as JS from Firefox itself).
Comment 6•4 years ago
|
||
The <svg>
element in the <style>
node gets removed because we sanitize <style>
nodes by getting their text content, sanitizing it, and then setting its new text content to the sanitized value, which automatically removes any non-text nodes in the process.
Reporter | ||
Comment 7•4 years ago
|
||
if you check document.body.innerHTML after the assignment, you'll see that the attribute has disappeared.
Thanks :Gijs for the detailed explanation, I able to view DOM output as you mention:
> document.body.innerHTML = '<svg><style><svg onload="javascript:alert(1337)"></svg>'
> "<svg><style><svg onload=\"javascript:alert(1337)\"></svg>"
> Content Security Policy: The page’s settings blocked the loading of a resource at inline (“default-src”). debugger eval code:1
> document.body.innerHTML
> "<svg><style></style></svg>"
Sorry it's my fault not checking document.body.innerHTML
on about:config to check the DOM output. I was think it same as normal page (e.g example.com)
Reporter | ||
Updated•4 years ago
|
Reporter | ||
Comment 8•4 years ago
|
||
(In reply to Kris Maglione [:kmag] from comment #4)
Well, I'm pretty sure it's not warning about the
onload
attribute because the entire <svg> element is being dropped. As for why the SVG element is being dropped, I have no idea. It would be interesting to know, but as long as we're not actually executing the script, I'm happy.
Hi Kris and :Gijs I found out it able to execute script :D, please re-open the ticket.
Steps to reproduce
- Go to about:config
- Set
security.csp.enable
boolean fromtrue
->false
- Restart Firefox Nightly
- Go to about:config
- Insert
document.body.innerHTML = "<svg><style><image href='https://www.example.com' onerror='alert(9113)'></svg>"
to the console - XSS will execute
Although DOM output show "<svg><style></style></svg>"
, but script execution is still possible.
Reporter | ||
Comment 9•4 years ago
|
||
Comment 10•4 years ago
|
||
(In reply to Irvan Kurniawan from comment #8)
(In reply to Kris Maglione [:kmag] from comment #4)
Well, I'm pretty sure it's not warning about the
onload
attribute because the entire <svg> element is being dropped. As for why the SVG element is being dropped, I have no idea. It would be interesting to know, but as long as we're not actually executing the script, I'm happy.Hi Kris and :Gijs I found out it able to execute script :D, please re-open the ticket.
I'm not sure if this is going to be materially different from bug 1666300 - I think if we fix that, this bug will be fixed, too. But we can reopen this to make sure we don't miss it going forward.
Updated•4 years ago
|
Reporter | ||
Comment 11•4 years ago
|
||
(In reply to :Gijs (he/him) from comment #10)
(In reply to Irvan Kurniawan from comment #8)
(In reply to Kris Maglione [:kmag] from comment #4)
Well, I'm pretty sure it's not warning about the
onload
attribute because the entire <svg> element is being dropped. As for why the SVG element is being dropped, I have no idea. It would be interesting to know, but as long as we're not actually executing the script, I'm happy.Hi Kris and :Gijs I found out it able to execute script :D, please re-open the ticket.
I'm not sure if this is going to be materially different from bug 1666300 - I think if we fix that, this bug will be fixed, too. But we can reopen this to make sure we don't miss it going forward.
Hi :Gijs thanks for re-opening this report.
In my opinion, it would be great to merge this report to bug 1666300 (edit the title it also able to bypass the HTML Sanitizer)
Updated•4 years ago
|
Updated•4 years ago
|
Comment 12•4 years ago
|
||
Hi Daniel, bug 1666300 has been classified as sec-moderate and seems to be most likely the cause for this as of comment 10. Should we reconsider classification here or there?
Comment 13•4 years ago
|
||
bug 1666300 was classified sec-moderate because it involved copy/paste (user action) in a web context. This bug points out that the same mechanism impacts our defense-in-depth against privilege escalation attacks into a browser/chrome UI context, which is properly rated sec-high (it's a kind of "sandbox escape"). We probably don't need so many bugs tracking what it almost surely the same underlying problem, but whatever bug remains should be sec-high.
One worry about coalescing bugs is that we lose testcases/scenarios we have to verify along the way, and then end up missing edgecases and embarrassing ourselves when we announce the incomplete fix. E.g. there may be special-case code around svg
vs. other elements. Since we have a sec-high problem to solve it should be handled quickly and a temporary overcount of a sec-moderate or two don't really matter.
Updated•4 years ago
|
Comment 14•4 years ago
|
||
This was fixed as bug 1667113 from the same reporter.
Reporter | ||
Updated•4 years ago
|
Updated•4 years ago
|
Updated•4 years ago
|
Updated•9 months ago
|
Description
•