Tuesday, 6 May 2014
Mutation XSS was coined by me and Mario Heiderich to describe an XSS vector that is mutated from a safe state into an unsafe unfiltered state. The most common form of mXSS is from incorrect reads of innerHTML. A good example of mXSS was discovered by Mario where the listing element mutated its contents to execute XSS.
<listing><img src=1 onerror=alert(1)></listing>
When the listing’s innerHTML is read it is transformed into an image element even though the initial HTML is escaped. The following code example shows how the entities are decoded.
<listing id=x><img src=1 onerror=alert(1)></listing>
The expected result of the alert would be “<img src=1 onerror=alert(1)>” however IE10 decodes the entities and returns “<img src=1 onerror=alert(1)>” instead. The vector mutated from a safe state to an unexpected unsafe state. mXSS can work on multiple reads of the data, the first render is the actual HTML and every read of innerHTML is counted as another mutation since it could be decoded multiple times.
To help testing for mutation vectors I’ve created a simple tool that mutates the HTTML multiple levels. It does this by reading and writing the HTML. The tool is available here:
If you try the above vector using this tool you can see how the vector mutates and executes. Because mutation XSS works on multiple levels the following HTML will be perfectly valid if you change the mutation level to 2. This reads and writes the HTML twice, you can of course increase the mutation value and continue encoding forever.
<listing>&lt;img src=1 onerror=alert(1)></listing>
HTML parsers often get confused and understandably because of the complex interaction between HTML, entities and different document types. One of those confusions happens with HTML and XHTML. In IE9 document mode the entities will be decoded by confusing the parser that it’s a XHTML element rather than a HTML element. Visit the mXSS tool in IE9 mode at the following URL
By using a forward slash which is ignored in HTML but in XHTML it’s treated as a self-closing element we confuse the HTML parser into rendering the entities and breaking out of the style element and executing an image element. This bug was fixed in IE10 but thanks to the useful backwards compatibility modes we can render using IE9 and still execute.
<style/></style><img src=1 onerror=alert(1)></style>
More elements work this way in IE9, the following Shazzer URL shows which elements decode entities in this way.
Another cool IE9 mutation vector is using the “<%” element, this element acts as a comment and it’s possible to mutate attributes inside other elements combining a script based vector. An example is below.
<div title="%></script>"<img src=1 onerror=alert(1)>"></div>