In a reflected DOM-based XSS, the server processes data from the request, and echoes the data into the response. The reflected data is placed within the DOM, such as a <span> HTML element. A script on the page then processes the reflected data in an unsafe way, ultimately writing it to a dangerous sink (e.g. element.innerHTML).
Additionaly, we will be using Burp Suite’s DOM Invader to instrument the Document Object Model (DOM). We can learn more about what source allows user-controlled input by using a unique string that’s used to see where our user input is reflected inside a sink.
Note: Obviously for legal reasons we can’t show this on the real site, so here it is in a lab we built to test it out.
As a initial attempt we used <img> tag combined with “on” event attribute (E.g. onerror) to see if we can run unrestricted JavaScript.
Firstly we can notice the span element called medium, which shows only first 7 characters (<img src) from our malicious string. The payload gets truncated and rest of it seem to be moved to span element dark. The full html string is then assigned to element.innerHTML.
<span class=”light”>Producten van </span> <span class=”medium”>1337test<img src </span> < span class=”dark”>onerror=prompt(document.domain)> </span>
At this point, we might like to add some extra characters to our payload in the URL parameter to see what behavior we get.
https://hack.lan/dev/support.htm#/account-management/view-account-products/1337testabcdefghijklmnopqrstuvwxyz<img src onerror= prompt(1)>
We added 34 characters to the beginning of our malicious string to see if truncation will appear at any point.
<span class=”light”>Producten van </span> <span class=”medium”>1337 testabcdefghijklmnopqrstuvwxyz <img src </span> <span class=”dark”>onerror= prompt(1)> </span>
We assume that the URL path can be controlled by an attacker – then we just need to find out how truncation works as we must have a valid HTML structure to launch an XSS attack.
As we know URLs cannot contain spaces. URL encoding normally replaces a space with a plus sign or with %20. Let’s add two instances of space %20 at a random position (must be before < Less-than sign) in our string to see if any truncation will appear.
https://hack.lan/dev/support.htm#/account-management/view-account-products/1337test%20<img%20src%20onerror=prompt(1)>
The string appeares to be truncated in different point and now our malicious payload moved three characters to the right (e.g from span element medium to dark).
Let’s add three more instances of space %20 just before less-than sign and then check if now we have a valid HTML structure
https://hack.lan/dev/support.htm#/account-management/view-account-products/1337test%20%20%20%20<img%20src%20onerror=prompt(1)>
The <img> tag moved to the right and now under span element dark we can see our malicious payload together with a popup.
Cross-Site Scripting (XSS) attacks can have a significant impact on both the targeted website and its users. Here are some of the potential consequences of a successful XSS attack:
- Theft of sensitive information: An attacker can use an XSS attack to steal sensitive information, such as login credentials, credit card numbers, or other personal data that may be entered into the targeted website.
- Malware distribution: An attacker can inject malicious code into a website through an XSS attack, which can then be used to distribute malware to unsuspecting visitors of the website.
- Website defacement: An attacker can use an XSS attack to deface a website, replacing its content with their own message or content.
- Phishing attacks: An attacker can use an XSS attack to create a convincing phishing page that looks like the targeted website, tricking users into entering their login credentials or other sensitive information.
- Reputation damage: A successful XSS attack can damage the reputation of the targeted website, as users may lose trust in the website’s security and reliability.
Here are some recommendations to help prevent and mitigate the impact of XSS attacks:
The best way to fix DOM based cross-site scripting is to use the right output method (sink). For example if you want to use user input to write in a div tag element don’t use innerHtml, instead use innerText or textContent. This will solve the problem, and it is the right way to re-mediate DOM based XSS vulnerabilities.
Additionally, we currently recommend using https://github.com/cure53/DOMPurify/ as your sanitizer. Essentially, we allow all code as long as it is wrapped in a function call to a known sanitizer like so:
element.innerHTML = DOMPurify.purify(evil);