I was unable to find any good documentation or anything on mXSS. Can anyone give some info or give a link?

I found a video and a PDF of the video's presentation:




mXSS is a new type of XSS attack by Mario Heiderich. I actually saw him present this very talk at Syscan 2013 this year.

The vulnerability in question comes from innerHTML which allows direct manipulation of HTML content, bypassing the DOM. An elements innerHTML is non-idempotent. The browser manipulates the contents to fix and optimize errors with the HTML. This is very visible in the example given in the slides. The problem with this manipulation is that it sometimes introduces flaws that is not apparent at first sight. One good example is also in the slides.

The big deal about this attack is that it bypasses (at the time of the talk, situation may be better now) most of the existing XSS filters and sanitizers.

As far as I know, there isn't any other available information about this class of XSS attack besides whatever information is present in the presentation slides.

  • 3
    "Mario-XSS" hah, JS. Mario is a freakin' bad ass, solid research from that guy. – rook Dec 11 '13 at 17:14
  • @Rook Heh, the "m" actually stands for mutation. :P – Ayrx Dec 12 '13 at 2:36
  • does it even by-pass encoded text areas? @TerryChia yeaah they call it "mutationXss" but i am pretty sure if his name didn't start with an m, it would be something else :D – cengizUzun Dec 12 '13 at 7:41
  • @cengizUzun I can't recall, but I think yes, if the textarea in question is being used by code calling .innerHTML – Ayrx Dec 12 '13 at 11:48
  • 1
    @TerryChia so there is no way to get rid of it? – cengizUzun Dec 12 '13 at 12:18

This is a kind of an ancient post, but some comments were asking if there was any defense.

Here's an excerpt from the paper:

At this point the string is still harmless and cannoot be used to execute an XSS attack. However, as soon as this string is inserted into the browser's DOM by using the innerHTML property, the browser will mutate the string. This mutation is highly unpredictable since it is not part of the specified innerHTML handling, but is a proprietary optimization of HTML code implemented differently in each of the main browser families. The mutated string now contains a valid XSS vector, and the attack will be executed on rendering the new DOM element. Both Server and client filters were unable to detect this attack because the string scanned in these filters did not contain any executable code.

This exploit is actually a BROWSER-BASED exploit. And in the world of rather dynamic frameworks like angularjs and jquery, there's quite a bit of innerHTML going on under the hood, even in 2012-2013 when this attack was first described.

The author goes on to say:

If innerHTML is only used to insert trusted code from the webapplication itself into the DOM, it is not vulnerable.

So the answer to "is there anything we can do?" is: Don't use innerHTML in combination with user input.

But wait... what if my application has thousands of calls to innerHTML or we use jquery? The paper discusses a script they offered called "TrueHTML." When looking for example code, the best I was able to find was here, where you override the client's use of innerHTML, bypassing the functions discussed in the original attack... and without needing to do more than to add a single script file. The paper also discusses a minimal performance hit.

(I'm not 100% sure if the code listing I used ought to be trusted--I didn't write it, copy-pasta at your own risk! That said, it appears to use the technique described in the paper.) I'm not sure if the "isExploitable" check returns a proper value.

Here's an excerpt from the provided github commit:

mitigateMXSS: function (element) {
 +      var that = this;
 +      if (typeof element.innerHTML === 'string') {
 +          Object.defineProperty(element, 'innerHTML', {
 +              get: function () { return that.changeInnerHtmlHandler(this, 'innerHTML') },
 +              set: function (html) {
 +                  while (this.firstChild) {
 +                      this.removeChild(this.lastChild);
 +                  }
 +                  this.insertAdjacentHTML('afterBegin', html);
 +              }
 +          });
 +      }
 +  },

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.