Cross-site scripting

Cross-site scripting or XSS is, from the web app developer's perspective, another name for arbitrary JavaScript injection. It works like this:


 * An attacker tricks an authenticated user into visiting a specially crafted URL, or a website which they control which can redirect them to the crafted URL.
 * The URL points to your web app and includes Javascript in the query string. The web app, due to poor escaping, injects the arbitrary JavaScript into the page that gets shown to the user.
 * The Javascript runs with full access to the user's cookies. It can modify the page in any way, and it can submit forms on behalf of the user. The risks are especially severe if the victim is an administrator with special privileges.

Example:

The attacker sends the victim to a URL like:


 *  http ://example.com/wiki/SomePage?class='%20>&lt;script>hack; &lt;/td>&lt;td%20class='

Note that POST requests are also vulnerable, using offsite JavaScript.

To avoid this, the basic principles are:


 * Validate your input
 * Escape your output

You can skip validation, but you can never skip escaping. Escape everything.

It doesn't matter if the escaping is redundant with the validation, the performance cost is a small price to pay in exchange for a demonstrably secure web app. It doesn't matter if the input comes from a trusted source, escaping is necessary even then, because escaping gives you correctness as well as security.

Escape as close to the output as possible, so that the reviewer can easily verify that it was done. It helps you to verify your own code, as well.

All this is true of any text-based interchange format. We concentrate on HTML because web apps tend to generate a lot of it, and because the security issues are particularly severe. Every text format should have a well-studied escaping function.

We also have some convenience functions in Xml.php which do HTML escaping for you.

MediaWiki also has some elegant building interfaces which implicitly escape things. For SQL using the 'key' => 'value' syntax of conditions implicitly escapes values. And the Html:: and Xml:: interface methods escape attributes, and depending on the method used may escape a text value as well.