Difficulty: Apprentice
Vulnerability: DOM-based Cross-Site Scripting (XSS) via document. write
Lab Link: https://portswigger.net/web-security/cross-site-scripting/dom-based/lab-document-write-sink-inside-select-element
The objective of this lab was to exploit a DOM XSS vulnerability where user input is written dynamically into a specific HTML element.
My goal was to identify the context of the injection (inside a
<select> menu), break out of that context, and execute the alert()
function.
I started by checking the “Check Stock” functionality on a product
page. I noticed that after checking stock in a specific city, the
URL contained a storeID parameter.
Upon carefully inspecting the request in Burp Suite, I found the use of an unsafe way of accepting the input from the users without validating it for any harmful expressions that might be there.
In the above screenshot, this piece of code
var store = (new URLSearchParams(window.location.search)).get('storeId');
document.write('<select name="storeId">');
if(store) {
document.write('<option selected>'+store+'</option');
}
for(var i=0;
i<stores.length;
i++) {
if(stores[i] === store) {
continue;
}
document.write('<option>'+stores[i]+'</option>');
}
document.write('</select>');
This line in the above code
var store = (new URLSearchParams(window.location.search)).get('storeId');
Expects a parameter storeId in the URL which initially is not there
when checking for the stocks in the web application, so we can add
this parameter in the URL from ourselves using &storeId=.
The very next line
document.write('<select name="storeId">');
and the last line
document.write('</select>');
This is what the lab also hinted, that this new parameter which accepts
the user input is stuck between the <select> ... </select> tags,
and unless we escape these tags, we cannot get our alert(1) to get
executed.
As we already mentioned in the reconnaissance step also how the lab
hinted that the dangerous write function is included between the
<select> ... </select> tag and our primary job is to be able to
escape this and once we escape this tag we can get our command to be
executed.
And the next thing is that the user controlled input needs to be sent
via a parameter, storeId where we are going to send our payload.
Step 1: Add the new parameter
We will add the new parameter in the URL along with productId using &storeId and add our payload
Step 2: Escape the
We can escape this simply closing the tag </select> and after this we can add our own payload that we want to get it executed.
Based on the above two conditions, we can use a payload like this one
Payload: &storeId=</select>
We successfully exploited the vulnerability that existed in the web application.