DOM-based Cross-site Scripting (from now on called DOM XSS) is a very particular variant of the Cross-site Scripting family and in web application development is generally considered the amalgamation of the following:

The Document Object Model (DOM) – Acting as a standard way to represent HTML objects (i.e. <div></div>) in a hierarchical manner.

Wherein DOM XSS uses the DOM to exploit XSS by relying on the insecure handling of user input on a static or dynamic HTML page. This is particularly common when applications leverage common JavaScript function calls such as:

document.baseURI

To build some part of the page, without sanitizing the return value. That said, the purpose of this article isn’t to explain DOM XSS fully, but rather how to defend against it.

Example

On one of our Test HTML5 applications there is a DOM XSS vulnerability that can be exploited via the following payload:

Which would look something like the following image – an informational message with a simple alert. Note how the payload is stored in the GET request, making it suitable for Social Engineering attacks.

The above is quite trivial but is an easy way to prove our point. The payload is embedded in the URI and so can be easily made part of a phishing campaign. The payload can be manipulated to deface the target application using prompt stating, “Your session has expired. Please insert your password to refresh your session”. A simple yet effective way to harvest passwords.

If we dig deeper, we find out that the #redir route is being executed by another file, called redir.html found here. If you view the source of the page, the gist of the code is as follows:

Essentially we are exploiting the window.location.hash source which is evaluated in an HTML Element Sink. For information on Sources and Sinks I highly recommend going over our other article explaining just that.

Remediation

Detecting DOM XSS is difficult using purely server-side detection (i.e. HTTP requests), which is why Acunetix leverages DeepScan to do it. These payloads are never sent to the server due to being behind an HTML fragment (everything behind the # symbol).

As a result, the root issue is in the code (i.e. JavaScript) that is in the page. This means that you should always sanitize user input, irrespective of whether or not it is client-side.

If you have to use user-input at any point in time on your page, always use it in the context of literal “text” and never as potential code. Avoid methods such as:

document.innerHTML

And instead use safer functions when using user input like so:

document.innerText
document.textContent

This will treat the previous payload we showed as just text and nothing else. Additionally, avoid using user input entirely especially ones that can affect:

URL

location

referrer

The above three properties may manipulate the DOM thus leading to such vulnerabilities. Keep in mind that DOM XSS and XSS are not mutually exclusive, meaning that your application can most definitely be vulnerable to both XSS and DOM XSS—even though XSS is normally found in dynamic pages and DOM XSS in static ones. The good news is that if user input is handled properly as a foundational level (e.g. your framework), then you should be able to mitigate all XSS-based vulnerabilities.

Conclusion

Lastly, leveraging a Web Application Scanner such as Acunetix will greatly increase both the speed and accuracy to which developers and security professionals can detect vulnerabilities like DOM XSS and fix them and thousands more. Acunetix can help completely secure your web application(s).