Okay let's tackle this beast, as i am writing this, i'm trying to prepare you for what's coming because this will not be easy at all. Burp suite pro makes it somewhat easier but even then, you still need to be able to interpret the scan results and exploit the vulnerability. This is where many hackers will fail. It's as simple as that, this is not something you do for fun, this is serious business.

This vulnerability often goes unnoticed as it's hard to detect so that means it's quite common in production enviornments.

What is DOM XSS

To tackle this question we first need to answer what the DOM is. I will not go too deeply into this topic as it can be very complex and goes back to how webpages are built. You are technically not even viewing the DOM if you looking at the source code of a webpage as the DOM goes back one step and describes how a webpage is built up to javascript so that JS can then convert that DOM into objects and manipulate it. To inspect the DOM properly this means that we MUST USE THE DEVELOPER CONSOLE AND NOT INSPECT SOURCE.

DOM XSS vulnerabilities usually arise when we can control input that is being passed into the DOM via a so called "DOM Sources" that then get passed into "DOM Sink" that supports dynamic code execution. Some examples can be eval() , document.write(), ...

Just like the source-based XSS we are well known with, DOM XSS also knows reflected and stored variants which obey the same rules as source-based XSS. If a variable is being reflected from a GET or a POST parameter into one of these sinks we are talking about reflected DOM XSS. If the variable comes from a value stored in the DB, we are talking about stored DOM XSS.

DOM Sink

When we talk about DOM sinks, we talk about locations where user controlled data will enter the DOM. There are 3 types of DOM sinks and we will go over all of them.

Document sink


In this example we are speaking to the innerHTML of an element in the DOM. This is a document sink since we are talking to an element in the document.

It's very important to note that your regular “<script>alert(1)</script>” won't work here besides several other attack vectors because this is a DOM insertion, not just a reflection of a value. When we speak of a DOM insertion. This is one of the reasons why uncle rat always tests with

<img src=x onerror=confirm()>

Some more examples:


Location sink


In this example we are speaking to the domain. The domain property of the Document interface gets/sets the domain portion of the origin of the current document. This means we are controlling the location and we are speaking to a location sink. In location sinks we usually have to work with javascript pseudo-protocols

example of pseudo-protocol: (http://blabla.com/test?url=javascirpt:alert())

More examples of location sinks;


Execution Sink


In an execution sink we will have the javascript code update it's own code with data that we as an attacker enter into the system.

In real life you will rarely find these sinks unprotected, you will often have to bypass some test that checks if you don't enter malicious code but these checks are usually built by the developer so if there is a flaw in their logic we can bypass that check.

DOM Source

A source is a JavaScript property that accepts data that is potentially attacker-controlled. An example of a source is the location.search property because it reads input from the query string, which is relatively simple for an attacker to control. Ultimately, any property that can be controlled by the attacker is a potential source. This includes the referring URL (exposed by the document.referrer string), the user's cookies (exposed by the document.cookie string), and web messages.

Common sources:


Testing for DOM XSS

Testing for DOM XSS is not always as simple as testing for source-based XSS. We NEED to use the developer tools to test for this as the values will appear in the DOM, not in the source code.

Testing for document sinks

To test for document sinks we will need to

Note that browsers behave differently with regards to URL-encoding, Chrome, Firefox, and Safari will URL-encode location.search and 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.

Testing for JS execution sinks

Testing for JS execution sinks is a little bit harder. With these sinks it can be that your input does not even appear anywhere within the DOM which makes it impossible to search for. In this case we will need to use the JS debugger to find out if our input is being passed into a sink.


So, amazing hacker, you may see that DOM based vulnerabilities are very complex and this is just the beginning of what the DOM has to offer. I hope you enjoyed this tutorial and i wish you a million bugs.