Closed Bug 796106 Opened 13 years ago Closed 12 years ago

XSSI - Bypass of E4X Security Protections

Categories

(Core :: JavaScript Engine, defect)

14 Branch
x86
macOS
defect
Not set
normal

Tracking

()

RESOLVED FIXED
Tracking Status
firefox15 --- wontfix
firefox16 --- wontfix
firefox17 --- unaffected
firefox-esr10 --- wontfix
b2g18 --- unaffected

People

(Reporter: breen.machine, Unassigned)

Details

(Keywords: reporter-external, sec-moderate, Whiteboard: [js:t])

User Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/537.4 (KHTML, like Gecko) Chrome/22.0.1229.79 Safari/537.4 Steps to reproduce: For security purposes FireFox does not allow E4X to constitute an entire script. This is necessary to mitigate the risk of cross site script inclusion attacks. The error message returned by the browser is: "SyntaxError: XML can't be the whole program" There is a simple method to bypass this protection. Consider the following page template: <b>Some other html and stuff</b> {{param1}}<p>This is supposed to be secret!</p>{{param2}} <i>More html after</i> Where the server replaces locations {{param1}} and {{param2}} with the querystring parameters param1 and param2. An attacker wishing to steal the data between {{param1}} and {{param2}} can include something like the following as a script in a page he controls (obviously replacing the alert function with something else): <script src="http://192.168.1.135:8000/?param1=alert('&param2=');"></script> A more interesting (and realistic example) is the following template: <b>Some other html and stuff</b> {{param1}} <p>This is supposed to be secret!</p> <b>so is this</b>{{param2}} <i>More html after</i> Here an attacker needs a slightly more complex injection (note the CDATA section wrapped in <r> tags): <script src="http://192.168.2.2:8000/?param1=var%20a%20%3d%20(<r><![CDATA[xxx&param2=yyyThis%20line%20is%20the%20second%20injection point]]></r>).toString()%3balert(a)%3b"></script> I have working PoC in the form of a Django web application that uses the example above.
We're unlikely to fix this because we'd rather make E4X die instead. See https://developer.mozilla.org/en-US/docs/E4X where it's marked deprecated, and as of Firefox 16 will no longer work in web content.
Assignee: nobody → general
Component: Untriaged → JavaScript Engine
Product: Firefox → Core
This attack requires the resource in question to look mostly like XML, without actually being XML (in particular, it must have multiple top-level elements and text at toplevel, outside all elements). I've never heard of anything quite like that. It's possible that such a thing exists on the web, but it must be rare. However, the attack can be extended to certain XML documents. Here's an example. If the resource is generated from this template: <data> {{ param1 }} <password>alfalfa</password> {{ param2 }} </data> and if an attacker can set param1 to {x= and param2 to } then after loading the document as a script, the global variable x will contain the E4X value <password>alfalfa</password>. All those characters { x = } are considered safe for XML text content; I wouldn't expect the server to escape them. This is a new flavor of XSS attack to me, though I'm no expert. Of course the attack requires a very particular kind of template, and it doesn't work in Aurora because E4X is pref'd off there.
I may be incorrect, but I believe this attack is possible any time the document is lacking a top level <html> element, is well formed, and does not have text outside of HTML elements. This doesn't seem like it would be exceedingly rare, although it definitely isn't the norm. The more interesting case would be, as your example demonstrates, AJAX calls and their responses where the responses return sensitive data.
Not entirely sure what comment 3 is saying, but comparing the aurora link to the equivalent beta version... https://hg.mozilla.org/releases/mozilla-beta/file/tip/modules/libpref/src/init/all.js#l681 ... I think it means MDN is wrong and E4X (in content) isn't going away until Firefox 17. If comment 3 means something else that delay appears to be true nonetheless :-(
Status: UNCONFIRMED → NEW
Ever confirmed: true
> ... I think it means MDN is wrong and E4X (in content) isn't going away until > Firefox 17. That's right, it's not going away until FF17. To fix in FF16 would involve backporting bug 765890 and bug 778851. It's doable.
The example I wrote in comment 4 wouldn't be vulnerable, because XML can't be the whole program. Duh. Sorry for the noise. breen.machine wrote in comment 5: > I may be incorrect, but I believe this attack is possible any time the document is > lacking a top level <html> element, is well formed, and does not have text outside > of HTML elements. No, additionally the attacker must be able to inject code outside of all HTML elements, which I think will be rare. And there's another weird requirement. Consider this template: <p>1</p> <p>2</p> {{param1}} <p>secret</p> {{param2}} The attacker cannot make this into a valid script because of the two adjacent paragraphs at the top. The < at the beginning of the second line is parsed as a less-than sign. SyntaxError.
OK. I think the full set of requirements to be able to exploit this are: - The attacker must control at least one injection point outside all elements, where some JS code can be injected. - The attacker must control injection points bracketing sensitive data or else right at the beginning of the document, outside all elements. - The document must not have any other top-level text, <!DOCTYPE>, or <?xml ...?> prolog outside of the elements. - Each element of the document must be well-formed, like XML. - The document must not have any two top-level elements that are adjacent. Now I think the most likely vulnerable document will be like this: {{param1}} <html> ...well-formed xml-like content... </html> The attacker can set param1 to "x=". It feels a lot like JSON-P. Another plausible possibility is like this: <html> ... {{param1}} ... <form ...> <input name="csrf-token" type="hidden" value="..." /> </form> ... {{param2}} ... </html> {{param3}} The attacker can set param1 to "{x=", param2 to "}", and param3 to "x".
Interesting. I hadn't seen the problem before with having multiple adjacent elements. To avoid the problem of needing to be outside of all elements, you could simply close the elements off in the beginning of your injection string. I guess this assumes that the application isn't filtering the "<" or ">" characters in the document body though, which means they probably have bigger problems.
(In reply to breen.machine from comment #10) > To avoid the problem of needing to be outside of all elements, you could > simply close the elements off in the beginning of your injection string. I > guess this assumes that the application isn't filtering the "<" or ">" > characters in the document body though, which means they probably have > bigger problems. Right, in that case the page has a cross-site scripting vulnerability that is exploitable in all the common browsers using a simple <script> tag. No need to bother with E4X.
sounds like this is still non-qualifying for a bounty due to the sec-moderate rating. does that sound right?
e4x was disabled for content in Firefox 17 (bug 778851) and removed completely from Firefox 21.
Status: NEW → RESOLVED
Closed: 12 years ago
Resolution: --- → FIXED
rforbes-bugspam-for-setting-that-bounty-flag-20130719
Flags: sec-bounty+
Group: core-security
You need to log in before you can comment on or make changes to this bug.