Cross-site Scripting (DOM based)

Severity: High
Summary#

Invicti detected a DOM based Cross-site Scripting (XSS).

Impact#

The Document Object Model (DOM) is a convention for representing and interacting with objects in HTML, XHTML and XML documents. Objects in the DOM tree may be manipulated by using methods on the objects.

All HTML documents have an associated DOM, consisting of objects representing the document properties from the point of view of the browser.

DOM Based 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. The response from the server does not change, but the client side code contained in the page executes differently due to the malicious modifications that have occurred in the DOM environment.

This is in contrast to other XSS attacks (stored or reflected), wherein the attack payload is placed in the response page (due to a server side flaw).

Example

Suppose the following code is used to create a form to let the user choose his/her preferred language. A default language is also provided in the query string, as the parameter "default".

…
Select your language:
<select>
  <script>
    document.write("<OPTION value=1>" + document.location.href.substring(document.location.href.indexOf("default=") + 8) + "</OPTION>");
    document.write("<OPTION value=2>English</OPTION>");
  </script>
</select>
…
		

The malicious script can be embedded in the URL as follows in two ways:

http://www.some.site/page.html?default=<script>alert(document.cookie)</script>
or
http://www.some.site/page.html#default=<script>alert(document.cookie)</script>

Pay close attention to the second version of the attack. When the victim clicks on the second link, the browser sends a HTTP request to:

http://www.some.site/page.html

The technique to avoid sending the payload to the server hinges on the fact that URI fragments (the part in the URI after the "#") is not sent to the server by the browser. Thus, any client side code that references (i.e, document.location) may be vulnerable to an attack which uses fragments, and in such case the payload is never sent to the server.

The server responds with the page containing the above JavaScript code. The browser creates a DOM object for the page, in which the document.location object contains the string.

The JavaScript code in the page does not expect the default parameter to contain HTML markup. The browser renders the page, starts building the DOM, and populates the document.url property of the document object with the URL containing the malicious script as follows:

http://www.some.site/page.html#default=<script>alert(document.cookie)</script>

Note that the HTTP response sent from the server does not contain the attacker’s payload. This payload manifests itself at the client-side script at runtime, when a flawed script accesses the DOM variable document.location and assumes it is not malicious.

Server-side attack detection tools will fail to detect such hash (#) attacks; in some cases, depending on the type of the URL, the server might get the payload and block the request.
Remediation#
  • Untrusted data should only be treated as displayable text. Never treat untrusted data as code or markup within Javascript code.
  • Avoid use of HTML rendering properties/methods. (e.g., innerHTML, outerHTML, document.write ). Instead use innerText or textContent.
  • Always encode Javascript and delimit untrusted data as quoted strings when entering the application.
  • Don’t evaluate JSON to convert it to native JavaScript objects. Instead use JSON.toJSON() and JSON.parse().

Build your resistance to threats. And save hundreds of hours each month.

Get a demo See how it works