DOM-based XSS

About DOM-based XSS
DOM-based XSS (or type-0 XSS) is a type of Cross-site scripting attack that occurs when client-side scripts (such as Javascript) manipulate the page's DOM, allowing an attacker to run javascript in the victim's browser.

This class of XSS is distinct from Reflective XSS (type-1 XSS) and Stored XSS (type-2 XSS), since the server is not returning executable Javascript to the browser. Instead, data that has been sanitized by the server, or possibly never sent to the server, is converted to executable Javascript by the existing code running on the page.

For example, consider this example script from the OWASP website:

... Select your language: document.write(""+document.location.href.substring(document.location.href.indexOf("default=")+8)+""); document.write("English"); ...

If the page is loaded with the 'default' parameter set to ' alert(“xss”) ' instead of the intended language string, then the extra script will be added into the page's DOM and executed as the page is loaded.

Preventing
Although Javascript can be added to MediaWiki sites without a formal code review process, these scripts can put other users in danger if they don't prevent these attacks.

As with standard XSS prevention, you should validate the data coming in when possible, and always escape the data as your script writes out to the page. In order to do this escaping, you should avoid using some methods that make escaping difficult, and instead use methods that make separation of HTML structure and values or text easy.

Avoid
In general, these functions should be avoided if possible. They can be made secure, but require an understanding of how each browser's Javascript engine works to make sure that all XSS vectors have been mitigated.

Element's .innerHTML and .outerHTML methods element.innerHTML = ' ' + user-data + ' ';

JQuery's .html method (which uses .innerHTML) $('#target').html( user-data );

Using user data in jQuery's element creation $( ' ' );

document.write or document.writeln document.write( 'Welcome to ' + user-data + '!' );

Using user data in a string passed to eval, setTimeout, an object's event handler, or javascript: url targets

Using user data in strings that generate CSS

Use
When updating the page's DOM, you should typically use this pattern of functions for creating DOM elements and inserting them into the DOM:

document.createElement("…") element.setAttribute("…", "value") element.appendChild(…)

Because the Javascript is able to clearly interpret what strings are meant to represent element names, attribute names, and attribute values, it will correctly escape any html characters that may have been inserted into user-controlled data.

With jQuery, you can use $(' ') to create the element, and any attributes that do not include user-controlled data. You can also use .attr to set the element's attributes, and .append or .appendTo to insert the element into the DOM.

The .text method can be used to set the text body of an element, and will correctly escape any html.

Sanitization
There may be times when you will need to mix user-controlled data with HTML. In those cases, you will need to ensure that the user-controlled data is properly escaped for the HTML context where it is being inserted.

For example, inserting data into the text of a div element:

User-Controlled Data

Requires different escaping than if you insert that user-controlled data into the id attribute of the div element.

A list of contexts and escaping rules can be found in the | OWASP XSS Prevention Cheat Sheet

For the most simple case (inserting user-controlled data into the text of an element), you can use mw.html.escape.