Research / Posted April 21, 2022
In an earlier blog post we looked at a basic introduction to Cross-Site Scripting or “XSS”, and how to prevent it when developing in-house web applications.
In that article we mainly focused on outlining how a basic form of XSS known as “Reflected XSS” works, because this is the simplest form to explain, as well as the form that is most commonly encountered, and the simplest for an attacker to exploit.
We also mentioned a variant known as “DOM XSS” in that article but didn’t dig further into exactly how it worked – that’s what we’re going to look at today. Strictly speaking, this form of XSS is more broadly referred to as “Client-Side XSS”.
First up – what’s the “DOM”?
“DOM” stands for “Document Object Model” and although you may not have heard of it, it underpins how every web browser interprets and renders web pages that are received from the server. It represents a web page as a document so that client-side scripting languages can change the structure, style, and content. Typically, web pages are transmitted and presented as HTML content, along with instructions on how associated static content should be rendered and displayed. However, this representation can all be manipulated and changed through client-side code talking to the programming interface exposed by the DOM.
The DOM is represented as an object-orientated tree structure of nested elements known as nodes. Each node represents an individual page element, and the DOM allows unique identification of each element in the tree via a dot-delimited and hierarchical “address”. For example a form may have the name “userDetails” and be addressable therefore as “document.userDetails”.
How does the DOM relate to XSS?
As a brief refresher, both reflected and stored XSS are ultimately “executed” on the client-side but rely on flaws in the handling of input or output processed by the server. That is, there is an input handler on the server somewhere that fails to correctly maintain the separation between executable code and user-provided data under certain conditions (a process that is typically ensured via measures such as robust input validation. The flawed input handler allows an attacker to send malicious data that causes the server to return or “reflect” unsanitized responses back to the client containing the attacker’s input as injected code, which the user’s browser then faithfully executes.
In server-side XSS, input is sent to the web server via HTTP requests using HTTP verbs (methods) such as GET or POST, with the user-supplied input appearing as included (or “reflected”) output unchanged within the response. The malicious input is said to be “reflected” back as part of the output code provided by the server to the client to be executed client-side. However, this same “input-output” mechanism exists client-side, albeit in a very different form, as we will outline below.
- add, change, and remove any of the HTML elements and attributes;
- change any of the CSS styles;
- react to all the existing events; and
- create new events.
What can go wrong with the handling of input client side?
The flawed code is ultimately still written by in-house developers, but the difference is that the code is not executed (or any input evaluated) on the server-side; the flawed code is simply handed to the user’s browser as a static resource for it to evaluate and make use of, and the XSS occurs when a specific event fires within the page running in the client’s browser, using user-provided input.
What is an example of DOM XSS in practice?
Let’s suppose that the following code is used to create a form to let the user select their 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>"+decodeURIComponent(document.location.href.substring(document.location.href.indexOf("default=")+8))+"</OPTION>"); document.write("<OPTION value=2>English</OPTION>"); </script></select>
The page is invoked with a URL such as:
A DOM Based XSS attack against this page can be accomplished by sending the following URL to a victim:
When the victim clicks on this link, the browser sends a request for:
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.
How prevalent is DOM XSS?
The graph below shows global Google search volumes for the term ‘Single Page Application.’ Note the sharp rise in popularity from around 2011.
How can I prevent DOM XSS?
Preventing DOM XSS requires sensible precautions be taken during each step of the software development lifecycle (SDLC) to prevent a robust series of measures that together reduce the overall risk:
- During the planning, analysis and design phases, architects should ensure that the risks of DOM XSS are properly understood, and the potential measures that can be taken to manage that risk understood. During this phase, appropriate libraries and frameworks are generally selected that can help support safe code construction.
- During the development phase, it is important that developers understand how to use appropriate escaping, encoding, and rigorous use of “safe” functions. This will depend greatly on appropriate developer training and education, as well as on the use of appropriate frameworks, libraries and methods selected during the earlier phase, in order to de-risk the introduction of potential DOM XSS vulnerabilities. The Open Web Application Security Project (OWASP) DOM Based XSS Prevention Cheat Sheet is a good resource that provides a list of best practice rules and guidelines to follow (https://cheatsheetseries.owasp.org/cheatsheets/DOM_based_XSS_Prevention_Cheat_Sheet.html). However, the most essential guidance is not too dissimilar to that for how to prevent other forms of XSS – escaping and encoding input received from untrusted sources before passing it for execution – albeit within the context of client-side rather than server-side code. Since it is very difficult to ensure that escaping and encoding are performed correctly if performed on an individual instance basis (i.e., remembering to do it every time), the use of “safe” libraries and frameworks can assist greatly in reducing the cognitive load and dependence on developers “getting it right every time”.
- During the testing phase, teams can combine careful manual peer code review/code audit with the use of linters and static analysers within CI/CD pipelines in order to enforce coding standards and catch unsafe method usage, or instances of input being handled directly rather than through approved libraries and frameworks. Testing can also incorporate web application vulnerability scanning using a tool such as AppCheck, to catch any vulnerabilities that may not have been caught in other checks. Since AppCheck can be integrated into Continuous Integration (CI/CD) pipelines, it can scan code in staging or other pre-production instances, highlighting vulnerabilities before they ever make it to production.
- During the implementation phase, teams can put into place further global or site-wide protection using a sensibly defined Content-Security Policy (CSP) that allows restrictions on all script execution and can, if configured correctly, reduce the likelihood of some forms of DOM XSS.
How can AppCheck Help?
AppCheck help you with providing assurance in your entire organisation’s security footprint. AppCheck performs comprehensive checks for a massive range of web application vulnerabilities – including DOM XSS vulnerabilities and client-side code weaknesses – from first principle to detect vulnerabilities in in-house application code.
The AppCheck Vulnerability Analysis Engine provides detailed rationale behind each finding including a custom narrative to explain the detection methodology, verbose technical detail, and proof of concept evidence through safe exploitation.
AppCheck is a software security vendor based in the UK, offering a leading security scanning platform that automates the discovery of security flaws within organisations websites, applications, network, and cloud infrastructure. AppCheck are authorized by the Common Vulnerabilities and Exposures (CVE) Program as a CVE Numbering Authority (CNA).
As always, if you require any more information on this topic or want to see what unexpected vulnerabilities AppCheck can pick up in your website and applications then please get in contact with us: firstname.lastname@example.org
Get started with Appcheck
No software to download or install.
Contact us or call us 0113 887 8380