Cross-Site Scripting (XSS) vulnerabilities are divided into three types:

  • Reflected: when payload is injected from user-provided payloads, e.g. user clicks on malicious link
  • Stored: when payload is stored on server-side (e.g. database) and is injected in the page content for all users
  • DOM: payload is stored in client browser

DOM-based XSS works similar to reflected one - attacker manipulates client's browser environment (Document Object Model) and places payload into page content. The main difference is, that since payload is stored in browser environment, it may be not sent on server side. This way all protection mechanisms related to traffic analysis will fail.

The payload may be stored in any DOM-tree element that is used in page content. For example, if we have following URL https://vulnbank.com/vulnbank/online/history.php?test=somedata#hashpart, these DOM-elements may be used for attack:

Description

In our case, vulnerable application has the following code

$("#history-searchinfo").html(
    "Searching... " + decodeURIComponent(location.hash.substr(1))
);

The request to https://vulnbank.com/vulnbank/online/history.php#<script>alert(1)</script> will inject <script>alert(1)</script> part to content of the page and it will be executed in the browser.

However, if we will look into the traffic, request to the server is sent without location.hash part

Showcase

Protection

Protection against this kind of attacks should be performed on client side. The easiest way is to use DOMPurify library that suppose to sanitize payload before injecting it into the page.
It requires following steps:

  • Include JavaScript-file:
<script type="text/javascript" src="src/purify.js"></script>
  • Call DOMPurify.sanitize function before injecting it into the page
var clean = DOMPurify.sanitize(dirty);

There is also jQuery library support with jPurify project from same developers team. To use it all you have to do - include two JavaScript-files

<script type="text/javascript" src="purify.js"></script>
<script type="text/javascript" src="jpurify.js"></script>

In our demo case, it'll prevent execution JavaScript in page contents.

Reference

OWASP: DOM-based XSS
OWASP: DOM-based XSS Prevention Cheat-sheet
DOMPurify Github page
jPurify Github page