DOM Cross-Site Scripting

Level: Practitioner

Today we will solve Portswigger’s “DOM XSS in document.write sink using source location.search inside a select element” lab from their XSS (Cross-site scripting) series.

This is what we know so far:

This lab contains a DOM-based cross-site scripting vulnerability in the stock checker functionality. It uses the JavaScript 'document.write' function, which writes data out to the page. The 'document.write' function is called with data from 'location.search' which you can control using the website URL. The data is enclosed within a select element. To solve this lab, perform a cross-site scripting attack that breaks out of the select element and calls the 'alert' function.

When we open the lab, we see a web store with different items. Let’s open one of them (I went with the first one). We can see that the URL of the page we are in is “https://YOUR-LAB-ID/product?productId=1”

Now let’s open the inspector and check the “Sources” tab. Our goal is to find a script that would have a source that we could control. Here we see a script that is telling us, in simplified terms, that window.location.search is being searched for storeID. Perhaps that is something we can work with…

When we open the “Console” tab in the inspector and type in “location.search”, we see a part of the URL reflected back to us:

So what happens when we add the parameter “storeId” to the URL? We can assume that it will also be reflected in location.search, right? Only one way to know for sure:

https://YOUR-LAB-ID/product?productId=1&storeId=somethingrandom

Well, yes, there it is. We have found our source:

Also, when we scroll to the bottom of the page we see that whatever we entered as the value of the “storeId” parameter has been added to the list of stores in the dropdown menu:

Now let’s see what it looks like in the “Elements” tab of the inspector:

Let’s try to escape the tags we are in (select and option) and then enter an XSS payload (e.g <script>alert(1)</script>) to see if we can trigger a popup. The URL will look like this:

https://YOUR-LAB-ID/product?productId=1&storeId=somethingrandom</option></select><script>alert(1)</script>

And we get the popup, congrats!

When we check the “Elements” tab, we see that we successfully managed to close the open tags and enter our script:

Of course, this is not the only XSS payload that works here. For example, instead of <script>alert(1)</script> we could also go for another simple one such as <img src=x onerror=alert(1)>.

That’s it for today, see you around!