Dom Based XSS

The vulnerability is in the client-side code rather than the server-side code.

Example

  1. The attacker crafts a URL containing a malicious string and sends it to the victim.
http://website/search?keyword=<script>...<script>
  1. The victim is tricked by the attacker into requesting the URL from the website.
GET http://website/search?keyword=<script>...<script>
  1. The website receives the request, but does not include the malicious string in the response. the original website code would be
<p>you searched for: <em></em></p>
<script>
  // notice this is the javascript code provided by the origianl website
  var keyword = location.search.substring(6);
  document.querySelector('em').innerHTML = keyword;
</script>
  1. The victim’s browser executes the legitimate script inside the response, causing the malicious script to be inserted into the page. then the website code would become
<p>you searched for: <em><script>...</script></em><p>
<script>
  var keyword = location.search.substring(6);
  document.querySelector('em').innerHTML = keyword;
</script>
  1. The victim’s browser executes the malicious script inserted into the page, sending the victim’s cookies to the attacker’s server.

What makes DOM-based XSS different?

For persistent and reflected XSS attacks, the server inserts the malicious script into the page, which is then sent in a response to the victim. When the victim’s browser receives the response, it assumes the malicious script to be part of the page’s legitimate content and automatically executes it during page load as with any other script.

In the example of a DOM-based XSS attack, however, there is no malicious script inserted as part of the page; the only script that is automatically executed during page load is a legitimate part of the page. The problem is that this legitimate script directly makes use of user input in order to add HTML to the page. Because the malicious string is inserted into the page using innerHTML, it is parsed as HTML, causing the malicious script to be executed.

The difference is subtle but important.

In traditional XSS, the malicious JavaScript is executed when the page is loaded, as part of the HTML sent by the server.

In DOM-based XSS, the malicious JavaScript is executed at some point after the page has loaded, as a result of the page’s legitimate JavaScript treating user input in an unsafe way.

Why DOM-based XSS matters?

In the previous examples (persistent and reflected), JavaScript was not necessary; the server could have generated all the HTML by itself. If the server-side code were free of vulnerabilities, the website would then be safe from XSS.

However, as web applications become more advanced, an increasing amount of HTML is generated by JavaScript on the client-side rather than by the server. Any time content needs to be changed without refreshing the entire page, the update must be performed using JavaScript. Most notably, this is the case when a page is updated after an AJAX request.

This means that XSS vulnerabilities can be present not only in your website’s server-side code, but also in your website’s client-side JavaScript code. Consequently, even with completely secure server-side code, the client-side code might still unsafely include user input in a DOM update after the page has loaded. If this happens, the client-side code has enabled an XSS attack through no fault of the server-side code.