XSS basé sur le DOM

This page is a translated version of the page DOM-based XSS and the translation is 32% complete.

A popos du XSS basé sur le DOM

Le XSS (cross-site scripting) basé sur les DOM (Document Object Model - modèle objet de document) ou XSS de type 0, est un type d'attaque XSS qui apparaît lorsque des scripts côté client (tels que du code JavaScript) manipulent le DOM de la page, permettant à un attaquant d'exécuter du JavaScript dans le navigateur de la victime.

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.

Exemple de script du site web OWASP :

...
Choisissez votre langue :
<select><script>
document.write("<OPTION value=1>"+document.location.href.substring(document.location.href.indexOf("default=")+8)+"</OPTION>");
document.write("<OPTION value=2>English</OPTION>");
</script></select>
...

If the page is loaded with the 'default' parameter set to '<script>alert("xss")</script>' 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.

Empêcher

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.

It can be tempting to use data attributes to provide information for javascript. This is generally good practice, but remember that users are allowed to make elements with arbitrary data attributes too, so any information taken from a data attribute (e.g. using jQuery's .data()) should be treated as untrusted input and validated.

Eviter

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 = '<div>' + user-data + '</div>';

JQuery's .html() method (which uses .innerHTML)

$('#target').html( user-data );

Using user data in jQuery's element creation

$( '<div id=' + user-data + '></div>' );

jQuery's append method, when you are not certain of the type and value of every node or object you are appending. If it is a string of (apparent) HTML, jQuery will implicitly convert it to an element.

document.write() ou 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

Utilisation

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

var $el = $('<div>');
$el.attr( {
  anAttribute: 'aValue',
  anotherAttribute: 'anotherValue'
} );
$el.text( 'Text of the div' );
$parent.append( $el );

As shown, you can use $('<tagName>') 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.

When you have a correctly constructed element, you can use .append() or .appendTo to insert the element into the DOM. But see above; do not use append() or appendTo() if you do not know exactly what you are appending.

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

If you're not using jQuery, you can use

var element = document.createElement( "tagName" );
element.setAttribute( "attributeName", "value" );
element.appendChild( child );

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.

Nettoyage

Dans certains situations il peut vous arriver d'avoir à mixer des données controlées par l'utilisateur et du HTML. Dans ces cas, il faut vous assurer que les données sous contôle de l'utilisateur sont convenablement échappées dans le contexte du HTML où elles sont insérées.

Par exemple, on insère des données dans le texte d'un élément div :

<div>User-Controlled Data</div>

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 jQuery's .text method or mw.html.escape().