OWASP Top 10 : Cross-Site Scripting #2 DOM Based XSS Injection and Mitigation

What is a DOM (Document Object Model)?

DOM is a W3C (World Wide Web Consortium) standard. It is a platform independent interface that allows programs and scripts to dynamically access and modify the structure of an document. The document can be HTML, XHTML or XML.

Let us apply the above definition practically:

Before modifying element using DOM: In the below figure, we have displayed an HTML element’s value using document.write function

After modifying element using DOM: In the below figure, we have used JavaScript to access and modify the value of element having id as demo.

We have changed it to ‘Changed!’. And the code responsible for it is:

document.getElementById("demo").innerHTML = "Changed!";

About DOM based XSS:

XSS also called as Cross Site Scripting is one of OWASP Top 10 attacks which results in client side code execution. Using XSS, an attacker can carry out attacks against the application users such as stealing cookies, creating a Trojan login form etc. There are 3 types of XSS:

  • Reflected (Type I)
  • Stored (Type II)
  • DOM Based (Type 0)

Unlike Reflected and Stored XSS, payload for DOM based XSS does not get delivered to the victim with server response. In fact, the payload never goes to the server within request. After server’s response reaches the browser, the malicious payload gets executed in an unexpected way by modifying the browsers DOM. The following picture represents the attack scenario:

 

The exploitation:

In the demo, we have a web app that has a DOM based XSS vulnerability. It has a URL based redirection functionality which will be of our interest.

Step by step guide of the redirection:

1. User clicks on this link: http://127.0.0.1/domxss/domxss.php#http://securelayer7.net

2. A GET Request goes to http://127.0.0.1/domxss/domxss.php. The request does not contain the URL written after # (i.e. https://securelayer7.net). Browsers consider it to be a client side data and do not send it as a part of request. However, browsers will process it after the response is received.

3. Response is received and the following HTML code gets loaded in web page.

4. The browser parses the HTML and JavaScript. As specified in JavaScript code,

The data after # is fetched dynamically and is passed to window.open to perform the required redirection and user gets redirected to https://securelayer7.net

Attacker crafts the URL:

The crafted URL is: http://127.0.0.1/domxss/domxss.php#javascript:alert(‘XSS’)

The payload that the attacker wrote using JavaScript protocol (javascript:) gets executed in the victim’s browser. This happened because after the response is received from server, the browser loads the vulnerable JavaScript.

And it executes whatever is written after # in the URL.

 

How to fix it?

In the payload: http://127.0.0.1/domxss/domxss.php#javascript:alert(‘XSS’), the expected data after # was a URL, but instead of that javascript:alert(‘XSS’) was supplied that resulted in the XSS. Now, lets try to fix it by making sure that the browser rejects anything that does not start from ‘http://’

So, the partially patched code is:

As you can see in line number 11, we have used a regular expression to validate that the input begins with ’http:’ and not ‘javascript’.

So, now if an attacker tries to use the earlier payload then, he will see the following page:

However, the above fix can be bypassed by crafting the URL which starts from ‘http:’ and directs victim to a link which contains the malicious script. So, the new payload becomes:

http://127.0.0.1/domxss/domxss.php#http://127.0.0.1:4567/myjs.html

So, we cannot rely on that fix. This means that use of black listing or regular expression has failed. So, the correct fix would be input validation by comparing with absolute value of URL. In our case the following URL is legitimate:

http://127.0.0.1/domxss/legitimateurl.html

So, the completely patched code is:

Now if a user tries to enter any URL of his choice, then it will be rejected and only the one given URL will be accepted. The legitimate page after redirection will look like:

So, we have seen how to find, exploit and patch DOM based XSS vulnerability. Thanks for reading. I hope you have enjoyed it.

References: