Testing for DOM-based Cross site scripting (OTG-CLIENT-001)

This is a draft of a section of the new Testing Guide v3

Brief Summary
DOM-based Cross-Site Scripting is the de-facto name for XSS bugs which are the result of active content on a page, typically JavaScript, obtaining user input and then doing something unsafe with it to lead to an XSS bug. This document will only discuss JavaScript bugs which lead to XSS.

There have been very few papers published on this topic and, as such, very little standardisation of its meaning and formalised testing exists.

Description of the Issue
Not all XSS bugs require the attacker to control the content returned from the server, but can rather abuse poor JavaScript coding practices to achieve the same results. The results are the same as a typical XSS bug, only the means of delivery is different.

One advantage that the exploitation of DOM Based XSS usually entails is the fact that often the server cannot determine what is actual being executed due to how the data is obtained from the client, as will be seen later, however this advantage is often moot since reflected XSS flaws can be transformed into trivial to exploit DOM Based XSS flaws. As such DOM Based XSS bugs should be treated the same as reflected XSS bugs.

Black and Gray Box testing and example
Blackbox testing for DOM-Based XSS is not usually performed since access to the source code is always available as it needs to be sent to the client to be executed. ...

Gray Box testing and example
Testing for Topic DOM Based XSS vulnerabilities: JavaScript applications differ significantly from other types of applications because they are often dynamically generated by the server, and to understand what code is being executed, the website being tested needs to be crawled to determine all the instances of JavaScript being executed and where user input is accepted. As many website rely on large libraries of functions, often stretching into the hundreds of thousands of lines, that they many have not even written themselves, top-down testing often becomes the only really viable option since many bottom level functions are never used, and analysing them to determine which are sinks will use up more time than is often availiable. The same can also be said for top-down testing if the inputs or lack thereof is not identified to begin with.

User input comes in two main forms: * Input written to the page by the server in a way that does not allow direct XSS * Input obtained from client-side JavaScript objects

Here are two examples of how the server may insert data into JavaScript: var data = ""; var result = someFunction("");

And here are two examples of input from client-side JavaScript objects: var data = window.location; var result = someFunction(window.referer);

While there is little difference to the JavaScript code in how they are retrieved it is important to note that when input is received via the server, the server can apply any permutations to the data that it desires, whereas the permutations performed by JavaScript objects is fairly well understood and documented, and so if someFunction in the above example were a sink, then the exploitability of the former would depend on the filtering done by the server, whereas the later would depend on the encoding done by the browser on the window.referer object.

Also, JavaScript is very often executed outside of blocks, as evidenced by the many vectors which have lead to XSS filter bypasses in the past, and so when crawling the application it is important to note the use of script in places such as event handlers and CSS blocks with expression attributes. Also note that any off-site CSS or script objects will need to be assessed to determine what code is being executed.