Web ApplicationJuly 21, 2023DOM-Based Cross-Site Scripting

As the digital landscape continues to evolve, so do the threats that target web applications. Cross-site scripting (XSS) remains a persistent and dangerous vulnerability among these threats. In particular, DOM-based XSS poses a significant risk to the security of web applications. In this blog, we will delve into the intricacies of DOM-based XSS, explore methods to detect and exploit these vulnerabilities and provide effective strategies to prevent them. 

What is DOM-based Cross-Site Scripting? 

DOM-based XSS vulnerabilities occur when JavaScript takes data from an attacker-controllable source. One example could be a URL. 

Subsequently, the data is then directed towards a receptacle that facilitates the execution of dynamic code, like eval() or innerHTML. This creates an avenue for malicious actors to run harmful JavaScript, potentially resulting in serious consequences such as account hijacking or other malevolent exploits.

The primary source of DOM-based XSS is the URL, often accessed using the window.location object. Attackers can construct links that direct victims to vulnerable pages, embedding payloads in the query string or fragment portions of the URL. The payload can sometimes be placed in the path, especially when targeting 404 pages or PHP-based websites. 

Detecting DOM-based Cross-Site Scripting Vulnerabilities 

Detecting DOM-based XSS vulnerabilities is crucial to ensure the security of web applications. While Burp Suite’s web vulnerability scanner provides a reliable automated option for detecting vulnerabilities, manual testing using a browser with developer tools is also effective. 

Testing HTML Sinks 

To test for DOM-based XSS in HTML sinks, insert a random alphanumeric string into the source (e.g., location.search) and use developer tools to inspect the HTML and locate where the string appears. Unlike the browser’s “View source” option, which doesn’t account for changes made by JavaScript, Chrome’s developer tools allow you to search the DOM for the string using Control+F (or Command+F on MacOS). 

Identify the context in which the string appears within the DOM and refine your input to test how it is processed. For example, if the string appears within a double-quoted attribute, attempt to inject double quotes into it to test if it can break out of the attribute. Note that different browsers handle URL encoding differently, which may impact the success of an XSS attack. 

Testing JavaScript Execution Sinks 

Testing JavaScript execution sinks for DOM-based XSS can become more challenging as the input may not directly appear in the DOM. To identify potential sources like location, you can search the page’s JavaScript code using Chrome’s developer tools by pressing Control+Shift+F (or Command+Alt+F on MacOS).

After finding where the source reads the data, use the JavaScript debugger to set breakpoints and trace how the value is used. If the source gets assigned to other variables, search again to track them and see if they pass to a sink. When you find a sink that receives data from the source, use the debugger to inspect the value, refine your input, and test for a successful XSS attack.

Using DOM Invader 

Identifying and exploiting DOM-based XSS vulnerabilities can be time-consuming, especially when dealing with complex, minified JavaScript. Burp Suite’s browser offers a helpful built-in extension called DOM Invader, simplifying this task by automating much of the work. 

Exploiting DOM-based Cross-Site Scripting 

Exploiting DOM-based XSS vulnerabilities requires an executable path for data propagating from source to sink. Different sources and sinks have unique properties and behaviors that affect exploitability and the techniques necessary to exploit them. Additionally, websites may perform data validation or other processing that must be considered during exploitation. 

One common sink for DOM-based XSS is the document.write function, which works with script elements. A simple payload can be injected as follows: 

document.write('... <script>alert(document.domain)</script> ...');  

However, it is important to consider the surrounding context of the document.write content, as additional elements may require closing or modifying before injecting the JavaScript payload. 

Another frequently used sink is innerHTML, which does not accept script elements on modern browsers. Alternative elements like img or iframe can be used, along with event handlers such as onload and onerror, to achieve similar effects: 

element.innerHTML = '... <img src=1 onerror=alert(document.domain)> ...';  

DOM-based Cross-Site Scripting in Third-Party Dependencies 

Modern web applications often rely on third-party libraries and frameworks, which introduce additional functions and capabilities. Recognizing that some dependencies may also introduce potential sources and sinks for DOM-based XSS vulnerabilities is crucial. 

DOM-based Cross-Site Scripting in jQuery 

When working with JavaScript libraries like jQuery, it is essential to be aware of sinks that can modify DOM elements on the page. For instance, jQuery’s attr() function can change the attributes of DOM elements. In case the data from a user-controlled source, such as the URL, is passed to the attr() function, it may be possible to manipulate the value and introduce XSS vulnerabilities. 

Consider the following example:

$(function() { $('#backLink').attr("href",(new URLSearchParams(window.location.search)).get('returnUrl')); });  

Exploiting this vulnerability involves modifying the URL to include a malicious JavaScript URL as the returnUrl parameter: 

?returnUrl=javascript:alert(document.domain)  

Be aware that even newer versions of jQuery may still be vulnerable via the $() selector sink. However, injecting HTML into a selector when the input begins with a hash character (#) is typically prevented in the latest versions. Nevertheless, legacy code or specific use cases may still present exploitable vulnerabilities. 

DOM-based Cross-Site Scripting in AngularJS 

Frameworks like AngularJS introduce their unique characteristics when it comes to DOM-based XSS. In AngularJS, you can execute JavaScript without angle brackets or events. When you use the ng-app attribute on an HTML element, AngularJS processes JavaScript within double curly braces, even if it appears directly in HTML or within attributes.

DOM-based Cross-Site Scripting Combined with Reflected and Stored Data 

DOM-based XSS vulnerabilities can self-contain within a single page. However, these vulnerabilities are not limited to data directly exposed by browsers as sources. Frequently, websites display URL parameters in the HTML response received from the server.

Reflected DOM-based Cross-Site Scripting 

In a reflected DOM-based XSS vulnerability, the server processes data from the request and echoes it back in the response.

The website may insert reflected URL parameter data into JavaScript or the DOM. A script on the webpage then processes this data unsafely, potentially writing it to a dangerous sink, creating security risks.

Consider the following example:

eval('var data = "reflected string"');  

Stored DOM-based Cross-Site Scripting 

In a stored DOM-based XSS vulnerability, the server receives data from one request, stores it, and then includes it in a later response. A script within the later response contains a sink that processes the stored data unsafely. 

Consider the following example: 

element.innerHTML = comment.author;  

Preventing DOM-based Cross-Site Scripting Vulnerabilities 

Preventing DOM-based XSS vulnerabilities requires a multi-faceted approach. In addition to the general measures discussed on the DOM-based vulnerabilities /web-security/dom-based page, it is crucial to avoid dynamically writing data from untrusted sources directly to the HTML document.

Implementing input validation, properly encoding data, and utilizing Content Security Policies (CSPs) are effective strategies to mitigate the risk of DOM-based XSS. Regular security assessments and code reviews are also essential to identify and address potential vulnerabilities. 

Web application developers can significantly reduce the likelihood of DOM-based XSS attacks, if they adopt these preventive measures. Moreover, it will enhance the overall security of their applications.

Understanding and mitigating the threat of DOM-based XSS vulnerabilities is essential for maintaining the security and integrity of web applications. Developers and security professionals can proactively detect, prevent, and remediate potential risks. They can do this by understanding the sources, sinks, and techniques used to exploit these vulnerabilities.

Through thorough testing, vigilant monitoring, and robust security practices, organizations can safeguard their web applications and protect their users from the perils of DOM-based XSS attacks. Stay informed, stay proactive, and stay secure. 

Redfox Security is a diverse network of expert security consultants with a global mindset and a collaborative culture. If you are looking to improve your organization’s security posture, contact us today to discuss your security testing needs. Our team of security professionals can help you identify vulnerabilities and weaknesses in your systems, and provide recommendations to remediate them.

“Join us on our journey of growth and development by signing up for our comprehensive courses.

Chirag Lundwani

by Chirag Lundwani

Security Consultant | Redfox Security