DOM-based XSS involves the execution of a payload as a result of modifying the DOM inside the browser used by a client side script. Since the payload resides in the DOM, the payload may not necessarily be sent to the web server.

This post covers the process of identifying the source of DOM-based XSS vulnerabilities discovered by Acunetix WVS through Acunetix DeepScan technology. This article requires a working knowledge of JavaScript as well as a sound understanding of how the DOM works within a web browser.  It is suggested that you read ‘DOM-based Cross-Site Scripting (XSS)’ Explained, which gives a good introduction to DOM-based XSS and how this type of XSS differs from traditional types of XSS.

Sources and Sinks

In order to understand how DOM-based XSS vulnerabilities work, one must first understand the difference between sources and sinks.

The source is the property that is read from the DOM. This is the property where a script can be injected to exploit a DOM XSS vulnerability. The sources listed hereunder are amongst some of the DOM properties that are most commonly exploited for DOM-based XSS.

Source Name Property susceptible to DOM-based XSS
Location / Document URL / URL document.URL

document.documentURI

location

location.href

location.search

location.hash

Referrer document.referrer
Window Name window.name

Source – https://code.google.com/p/domxsswiki/wiki/Sources

Sinks, on the other hand are the points in the flow of data at which the untrusted input gets outputted on the page or executed by JavaScript within the page. The following is a list of common sinks where DOM-based XSS ends-up being executed.

Sink Name Property susceptible to DOM-based XSS
Execution Sink eval

setTimeout

setInterval

HTML Element Sink document.write

document.writeIn

innerHTML

outerHTML

Set Location Sink location

location.href

Note – window.location or document.location and its properties can be both a source as well as a sink.

A Simple Example of DOM-based XSS

The following example is taken from OWASP’s DOM-based XSS article, and shall be used to demonstrate how DOM-based XSS is detected by Acunetix WVS. A more advanced, harder to detect example of DOM-based XSS is covered further on in this article.

The following HTML markup can be used to allow users to select a default language.

<html>
<head><title>DOMXSS</title></head>
</body>
Select your language:
<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>
</body>
</html>

The above markup renders the default language by making use of the query string. For instance, the following URL includes the parameter “German” in the query string.

http://www.example.com/dom-xss?default=German

Running a scan with Acunetix WVS on such a page will detect a DOM-based XSS vulnerability as indicated below.

Acunetix scan detecting DOM-based XSS

Reproducing this vulnerability is straightforward since the source of this DOM-based XSS vulnerability is actually in the Location which is an object in the DOM that can be used to get the current page address (URL). Therefore, considering the alert Acunetix WVS provides, by simply entering the following URL inside of a browser, the vulnerability is exploited since anything that is entered in the URL’s query string is being echoed back into the page (in the <select> control) without being sanitized first.

http://www.example.com/dom-xss?default=<script>alert("DOM XSS");</script>

Note – This example may not work in some browsers due to built-in XSS prevention mechanisms.

Acunetix WVS also provides the Execution Sink, which in this case is document.write. The JavaScript code embedded in the HTML markup in the example is simply taking whatever is placed in the query string inside the URL and echoing it in the page, thus exposing the page to a DOM-based XSS vulnerability.

A More Advanced Example of DOM-based XSS

While the example above is rather straight forward to understand and fix, some DOM-based XSS vulnerabilities are generally more complex to identify.

The screenshot below is taken from an Acunetix WVS scan of http://testhtml5.vulnweb.com. Under Attack Details, Acunetix WVS lists useful information which can be used to find the source of the issue and reproduce the vulnerability manually.

Acunetix scan of http://testhtml5.vulnweb.com

The information presented in the Attack Details section shows the following:

  • The Source of the vulnerability  – window.name
  • The data input used by Acunetix WVS to identify and exploit this vulnerability – In this case, Acunetix WVS set window.name to javascript:domxssExecutionSink(2,"<br>()wildxss")
  • The Execution Sink causing the data input to be executed – evaluate code section. Note that Acunetix WVS may not always determine the exact sink and will provide multiple possible Execution Sinks.
  • The Evaluated code, which is the code that shows where the payload was outputted to the page or executed.
  • The Stack Trace

With this information, it is now possible to identify and reproduce this vulnerability. The portion of the alert that details the source of the vulnerability provides an indication of which part of the DOM is being manipulated in the attack. In this case, the vulnerable parameter is window.name, which can be exploited with the following code hereunder (pop-ups need to be enabled).

<html>
<body>
<script>
window.open("http://testhtml5.vulnweb.com", "alert('DOM XSS');");
</script>
</body>
</html>

After being able to reproduce the vulnerability, a better understanding of the vulnerable portions of the JavaScript code is possible. Acunetix WVS provides the source of the vulnerability (in this case the source is reported as window.name), however, it is important to note that this is not necessarily the way it is being referred to in the vulnerable JavaScript file. In this case, Acunetix WVS reports that sessvers.js is vulnerable to DOM-based XSS via the window.name source. However, window.name is nowhere to be found in sessvars.js in the file. This will be explained further on, but first the Stack Trace provided by Acunetix WVS will be used to get more information.

The Stack Trace shows the flow of the active stack frames during the execution of the JavaScript code.

Checking line 105 in sessvers.js, as indicated in the Stack Trace (since a Stack Trace is built from bottom-to-top), reveals the DOM-based XSS sink; which is in fact an eval() function containing improperly escaped JavaScript found in variable x which is in-turn being set by the toObject function. eval() is indeed one of the possible execution sinks that Acunetix WVS reports in the above alert.

eval("this.myObj="+x);

When checking line 76, as per the Stack Trace, the toObject function is being passed top.name without any sanitization. toObject is the function that contains the DOM-based XSS sink as described above.

While this may be slightly confusing at first, upon taking a closer look, one may notice that the property vulnerable to DOM-based XSS in sessvars.js is top.name. The top object returns the top-most browser window and is in fact inheriting properties from window. This is the place where the source of the DOM XSS vulnerability is being read from the DOM.

SHARE THIS POST
THE AUTHOR
Ian Muscat

Ian Muscat used to be a technical resource and speaker for Acunetix. More recently, his work centers around cloud security and phishing simulation.