What is DOM-based cross-site scripting?
The most common source for DOM XSS is the URL, which is typically accessed with the
window.location object. An attacker can construct a link to send a victim to a vulnerable page with a payload in the query string and fragment portions of the URL. In certain circumstances, such as when targeting a 404 page or a website running PHP, the payload can also be placed in the path.
For a detailed explanation of the taint flow between sources and sinks, please refer to the DOM-based vulnerabilities page.
How to test for DOM-based cross-site scripting
The majority of DOM XSS vulnerabilities can be found quickly and reliably using Burp Suite's web vulnerability scanner. To test for DOM-based cross-site scripting manually, you generally need to use a browser with developer tools, such as Chrome. You need to work through each available source in turn, and test each one individually.
Testing HTML sinks
To test for DOM XSS in an HTML sink, place a random alphanumeric string into the source (such as
Command+F on MacOS) to search the DOM for your string.
For each location where your string appears within the DOM, you need to identify the context. Based on this context, you need to refine your input to see how it is processed. For example, if your string appears within a double-quoted attribute then try to inject double quotes in your string to see if you can break out of the attribute.
Note that browsers behave differently with regards to URL-encoding, Chrome, Firefox, and Safari will URL-encode
location.hash, while IE11 and Microsoft Edge (pre-Chromium) will not URL-encode these sources. If your data gets URL-encoded before being processed, then an XSS attack is unlikely to work.
For each potential source, such as
Exploiting DOM XSS with different sources and sinks
In principle, a website is vulnerable to DOM-based cross-site scripting if there is an executable path via which data can propagate from source to sink. In practice, different sources and sinks have differing properties and behavior that can affect exploitability, and determine what techniques are necessary. Additionally, the website's scripts might perform validation or other processing of data that must be accommodated when attempting to exploit a vulnerability. There are a variety of sinks that are relevant to DOM-based vulnerabilities. Please refer to the list below for details.
document.write sink works with
script elements, so you can use a simple payload, such as the one below:
document.write('... <script>alert(document.domain)</script> ...');
Note, however, that in some situations the content that is written to
innerHTML sink doesn't accept
script elements on any modern browser, nor will
svg onload events fire. This means you will need to use alternative elements like
iframe. Event handlers such as
onerror can be used in conjunction with these elements. For example:
element.innerHTML='... <img src=1 onerror=alert(document.domain)> ...'
attr() function in jQuery can change attributes on DOM elements. If data is read from a user-controlled source like the URL and then passed to the
href attribute using data from the URL:
You can exploit this by modifying the URL so that the
href, clicking on the back link will execute it:
DOM XSS combined with reflected and stored data
Some pure DOM-based vulnerabilities are self-contained within a single page. If a script reads some data from the URL and writes it to a dangerous sink, then the vulnerability is entirely client-side.
However, sources aren't limited to data that is directly exposed by browsers - they can also originate from the website. For example, websites often reflect URL parameters in the HTML response from the server. This is commonly associated with normal XSS, but it can also lead to so-called reflected+DOM vulnerabilities.
eval('var data = "reflected string"');
Websites may also store data on the server and reflect it elsewhere. In a stored+DOM vulnerability, the server receives data from one request, stores it, and then includes the data in a later response. A script within the later response contains a sink which then processes the data in an unsafe way.
element.innerHTML = comment.author
Which sinks can lead to DOM-XSS vulnerabilities?
The following are some of the main sinks that can lead to DOM-XSS vulnerabilities:
The following jQuery functions are also sinks that can lead to DOM-XSS vulnerabilities:
How to prevent DOM-XSS vulnerabilities
In addition to the general measures described on the DOM-based vulnerabilities page, you should avoid allowing data from any untrusted source to be dynamically written to the HTML document.