Reflected DOM XSS Lab – Portswigger Web Academy

Lately, I’ve been participating in some bug bounty programs and have been doing Portswigger’s web security labs as a refresher. This lab was particularly interesting to me because it forced you to use dev-tools to debug the application to figure out where exactly to inject. So in the post, I’ll walk you through how to use Firefox’s dev-tools to dig deeper into an application.

DOM XSS

For those of you who aren’t familiar with XSS (Cross-site Scripting), it’s a web vulnerability that allows unauthorized users to inject javascript code into a web application. This can be through form inputs, url parameters, or pretty much anywhere that gives the user a chance to pass input that is then rendered by the browser.

There are three types of XSS:

  • Reflected: the current HTTP(s) request triggers the malicious JavaScript
    • Ex: A maliciously crafted link the user has to click on to execute the code
  • Stored: the malicious script is rendered after it is pulled from a database
    • Ex: JavaScript stored in the comment section of a blog post.
  • DOM: malicious JavaScript is stored in the client-side in the document object model (DOM)
    • Ex: User input is fed directly to document.innerHTML

DOM XSS is usually the hardest to spot and wrap your head around because it occurs during runtime. So, in this post, I’m going to be running through one of Portswigger’s Labs to expose you to testing for these vulnerabilities using browser dev-tools.

The Lab

The lab I’m going to be walking you through is the Reflected DOM XSS lab, so feel free to follow along with me!

To solve this lab, we’re going to need to trick the site into calling the alert()function. First things first, we need to find out where this site is reflecting user input. The most immediate place to try passing user input is the big search bar on the homepage. So, I type a unique string (test12345) and use the dev tools to search for it.

To open up my dev tools, I right-clicked on the reflected value and selected “Inspect Element.” This value looks like it’s inserted directly into the <h1> tag but what stood out to me even more is the search('search-results') function call.

Let’s head to the debugger to see what that’s all about. Clicking on the link to searchResults.js took me to the debugger. Right away, this line stood out to me:

eval methods are notoriously vulnerable to XSS because they evaluate strings to JavaScript code. Whenever you’re testing for XSS be on the lookout for eval functions because they are often a golden ticket to XSS if input isn’t sanitized. The innerHTML attribute of should also be considered a red flag because it is used to directly insert HTML code inbetween tags. There were no lines containing innerHTML (only innerText and setAttribute handled our input) so let’s focus on the eval method for now.

So, I set a break point on the line containing the eval function (line 5) and ran another search. Once execution is paused, expanding the panel on the right for this reveals that response.responseText stores:

The same can be achieved by just hovering over the line in the code (but this was easier to screenshot). As you can see, responseText gets evaluated as a JSON object. Let’s try escaping the JSON with "}; and then calling the alert() function after:

It looks like a \ was used to escape the quote. Let’s try inserting a \ to see if we can escape the escape…

Not exactly what I was expecting but it looks like the logic of the code tried to escape the back-slash with a back-slash then tried to escape the one that was trying to escape the "…? Either way, it looks like they all canceled each other out.

Resuming the code and…nothing happened… That’s because I forget about the trailing "}! Adding a simple // should do the trick. Now our full payload looks like test\"}; alert(1); //:

Much better! Resuming the execution gives us an alert!

We did it!

Conclusion

Developer tools are often overlooked when web application testing but they are actually incredibly powerful. Taking the time to dive deeper into the application will allow you to look for mistakes that those who rely on automated tools and scanners will definitely miss! So, it’s important to examine the code and understand what it is the application is actually doing. This will put you 10 steps ahead against other bug bounty hunters!