How does malicious input flow in a DOM-based XSS

Cross-site scripting (XSS) is a very well-known web application vulnerability among developers. While the idea that attackers can inject JavaScript into your code is clear, the most important part of an XSS attack that developers must understand is its impact. If successful, an attacker can steal or hijack your session, carry out convincing phishing attacks, and effectively do anything that the victim can.

DOM-based XSS simply means a cross-site scripting vulnerability that occurs in the DOM (Document Object Model) of your site rather than in HTML. In reflective and stored cross-site scripting attacks, you can see the vulnerability payload in the response page. In DOM-based cross-site scripting, the HTML source code and response of the attack will be exactly the same, i.e. the payload cannot be found in the response. It can only be observed at runtime or by investigating the DOM of the page.

Simple DOM-based cross-site scripting vulnerability example

Imagine the page http://www.example.com/test.html that contains the following JavaScript code:

If you send an HTTP request like http://www.example.com/test.html#, your JavaScript code will be duly executed because the page is simply using document.write to write out whatever you typed in the URL. However, if you look at the source of the page, you won’t see  anywhere because it’s all happening in the DOM and done by the executed JavaScript code.

After such malicious code is executed by page, attackers can exploit this DOM-based cross-site scripting vulnerability to steal cookies from the user’s browser or change the behavior of the web application page with malicious intent.

DOM XSS vulnerabilities are a real threat

Various research and studies identified that up to 50% of websites are vulnerable to DOM-based XSS vulnerabilities. Security researchers have identified DOM-based XSS issues even in the sites and applications of the biggest web companies.

Server-side filters do not matter

One of the biggest differences between DOM-based XSS and reflected or stored XSS vulnerabilities is that DOM-based XSS can never be stopped by server-side filters. The reason is quite simple: anything written after the # (hash) is never sent to the server.

Historically, the hash character was introduced to simply scroll the HTML page to a certain item. However, it was later adopted by JavaScript developers for use in AJAX pages to keep track of the pages and various other things, mostly used as the so-called hash-bang (#!).

Due to this design, anything after the hash won’t be sent to the server. This means that no server-side protection in the code will work against DOM-based XSS. As a matter of fact, other types of web protection, such as web application firewalls, or generic framework protections like ASP.NET Request Validation, also will not protect you against DOM-based XSS attacks.

Input and output a.k.a. source and sink

The logic behind the DOM XSS is that an input from the user (source) goes to an execution point (sink). In the previous example our source was document.baseURI and the sink was document.write.

What you need to understand is that DOM XSS will appear when a source that can be controlled by the user is used in a dangerous sink.

Whenever you see this situation, you need to either make the necessary code changes to eliminate the DOM XSS vulnerability or add suitable encoding.

Below is a list of sources and sinks which are typically targeted in DOM XSS attacks. Note that this is not a complete list, but you get the idea: anything that can be controlled by an attacker is a source and anything that can lead to script execution is a sink.

  • Current URL: 
    0
  • Current URL: 
    1
  • Current URL: 
    2
  • Current URL: 
    3
  • Current URL: 
    4
  • Current URL: 
    5
  • Current URL: 
    6
  • HTML Modification sinks
    • document.write
    • Current URL: 
      8
  • HTML modification to behaviour change
    • Current URL: 
      9 (in certain elements)
  • Execution Related sinks
    • http://www.example.com/test.html0
    • http://www.example.com/test.html1 and http://www.example.com/test.html2
    • http://www.example.com/test.html3

Fixing DOM cross-site scripting vulnerabilities

The best way to fix DOM based cross-site scripting and improve web application security is to use the right output method (sink). For example, if you want to use user input to write into a http://www.example.com/test.html4 element, don’t use http://www.example.com/test.html5, but instead use http://www.example.com/test.html6 or http://www.example.com/test.html7. This will solve the problem and is the correct way to remediate DOM-based XSS vulnerabilities.

It is always a bad idea to use a user-controlled input in dangerous sources such as http://www.example.com/test.html0. 99% of the time, it is an indication of bad or lazy programming practice, so simply don’t do it instead of trying to sanitize the input later.

Finally, to fix the problem in our initial code example, instead of trying to encode the output correctly, which is a hassle and can easily go wrong, we would simply use http://www.example.com/test.html9 to write in some content like this:

Current URL: 

This example does the same thing, but this time it is not vulnerable to DOM-based cross-site scripting vulnerabilities.

Where does the malicious code in an XSS attack run?

Introduction to XSS Attack A cross-Site Scripting attack is a malicious code injection, which will be executed in the victim's browser. The malicious script can be saved on the webserver and executed every time when the user calls the appropriate functionality.

How does DOM based XSS work?

DOM Based XSS (or as it is called in some texts, “type-0 XSS”) is an XSS attack wherein the attack payload is executed as a result of modifying the DOM “environment” in the victim's browser used by the original client side script, so that the client side code runs in an “unexpected” manner.

What is DOM in DOM based XSS?

A DOM-based cross-site scripting (XSS) attack happens when a threat actor modifies the document object model (DOM) environment in the victim's browser. So, while the HTML itself doesn't change, the code on the client side executes differently. This type of attack is also sometimes referred to as “type-0 XSS.”

How does an attacker exploit stored XSS?

Stored XSS exploits occur when an attacker injects dangerous content into a data store that is later read and included in dynamic content. From an attacker's perspective, the optimal place to inject malicious content is in an area that is displayed to either many users or particularly interesting users.