Skip to main content
Create your own
Lesson illustration

XSS for CSRF: Unauthorized Actions

Hello! Welcome back to the course.

In our last lesson, you learned how to escalate a Cross-Site Scripting (XSS) vulnerability into a full account takeover by stealing session cookies. This is a classic and powerful attack. However, as we briefly discussed, developers can set an HttpOnly flag on cookies, which instructs the browser to prevent client-side scripts like JavaScript from accessing them.

This brings up a crucial question: If you can't access document.cookie, is an XSS vulnerability useless? Absolutely not.

Today, we'll explore a more sophisticated way to leverage XSS. Instead of stealing data, we will command the victim's browser to perform actions on our behalf. Your learning outcome is to craft an XSS payload to perform unauthorized actions on behalf of a victim user, a technique often called "CSRF via XSS". This demonstrates that even with HttpOnly cookies, XSS can still lead to critical impacts like account takeover.

1. From Stealing to Commanding: Bypassing CSRF Protection

First, let's quickly define Cross-Site Request Forgery (CSRF). It's an attack that tricks an authenticated user into submitting a request to a web application that they did not intend to. For example, an attacker could host a webpage with an image tag whose src attribute points to https://your-bank.com/transfer?to=attacker&amount=1000. If you visit that page while logged into your bank, your browser might automatically send the request with your session cookies, completing the transfer.

To prevent this, modern applications use anti-CSRF tokens. These are unique, unpredictable values that the application server generates for each user session. This token must be included in any sensitive request (like changing an email or transferring funds). An attacker on a different domain can't guess this token, so their forged request will fail.

Burp Suite: Identifying an Anti-CSRF User Token in an HTTP Request
This image shows an HTTP request in Burp Suite. The highlighted `user_token` is an example of an anti-CSRF token. The server will only process the request if this token is valid for the user's session.

This is where XSS changes the game. Because your injected JavaScript code runs on the same origin as the target application, it is not bound by the Same-Origin Policy. Your script can:

  1. Read the content of any page on that domain.
  2. Find the anti-CSRF token, which is often embedded in a hidden form field.
  3. Construct a valid request that includes the legitimate token.
  4. Send this request to perform a sensitive action (e.g., change the victim's password or email), all without the victim's knowledge.

This is the essence of performing CSRF via XSS. Your script acts as a malicious puppeteer inside the victim's browser.

The Nuharbor Security article "alert('XSS – Pwn3d!'): The Real Dangers of Cross-Site ..." provides a great conceptual overview of this technique.

alert('XSS – Pwn3d!'): The Real Dangers of Cross-Site ...

To solidify your understanding of the theory, let's read a section from this article. It clearly explains how XSS allows an attacker to bypass anti-CSRF defenses.

Read the section titled 'Anti-CSRF Bypass Using XSS'. Focus on the two-stage logic it describes: Request A: The script first makes a request to a page to retrieve the anti-CSRF token. Request B: The script then uses that stolen token to forge a second, malicious request to perform the sensitive action.

2. Crafting the Payload: A Practical Walkthrough

Now let's see how this works in practice. The process involves identifying a target action, finding the CSRF token, and scripting the attack.

This video provides an excellent end-to-end demonstration of exploiting a stored XSS to change a victim's email address by bypassing the CSRF token defense.

Exploiting XSS to perform CSRF

The video 'Exploiting XSS to perform CSRF' by z3nsh3ll will walk you through the entire attack chain. It's a perfect practical demonstration of the concepts we've just discussed.

Watch the video from 01:01 to 07:20, paying close attention to these steps: The problem (01:01 - 01:50): The presenter explains why a CSRF token normally prevents this attack and how XSS allows a bypass. Finding the token (02:12 - 03:10): Observe how the token is located in a hidden input field in the DOM and how it's accessed with a simple JavaScript command: document.getElementsByName('csrf')[0].value. Building the payload (03:10 - 05:44): This is the core of the lesson. Analyze the JavaScript payload. It uses the fetch API to construct and send a POST request containing the new email and the stolen CSRF token. Execution and Impact (05:44 - 07:20): The video shows the payload being executed in the victim's context, successfully changing their email and leading to account takeover.

As you saw, the payload consists of a few logical parts:

  1. Get the Token: var token = document.getElementsByName('csrf')[0].value;
  2. Prepare the Data: A FormData object is created to hold the parameters for the POST request, including the malicious email and the retrieved token.
  3. Send the Request: The fetch() API is used to send the POST request to the /my-account/change-email endpoint with the prepared data in its body.

This all happens silently in the background when the victim loads the page containing your stored XSS payload.

Test your understanding!

In the video, the CSRF token was in a hidden input field. What would you do if the token wasn't on the current page, but was only available on, say, the /my-account/change-email page itself? How would your script need to adapt? (Hint: Think about the Nuharbor article).

Show answer

Your script would need to perform the two-stage attack described in the Nuharbor article.

  1. First, it would use fetch or XMLHttpRequest to send a GET request to /my-account/change-email.
  2. Then, it would parse the response text of that request to find and extract the CSRF token (e.g., using regular expressions or string matching).
  3. Finally, it would use that extracted token to send the malicious POST request.

This is possible because the script, running on the same origin, is allowed to make requests to other pages on the site and read their responses.

3. Advanced Technique: Chaining XSS with CORS Misconfigurations

You can amplify the impact of XSS by chaining it with other vulnerabilities. A common and powerful chain involves XSS and a Cross-Origin Resource Sharing (CORS) misconfiguration.

Imagine this scenario:

  • The main application is at https://api.example.com. It has a sensitive endpoint like /users/delete.
  • The developers have misconfigured CORS to trust any subdomain, like *.example.com.
  • You find a simple reflected XSS on a forgotten blog at https://blog.example.com.

By itself, the XSS on the blog seems low-impact. But because of the CORS policy, a script running on blog.example.com is trusted to make authenticated requests to api.example.com. You can craft an XSS payload on the blog that, when a logged-in admin visits, sends a DELETE request to the API and deletes their account.

Let's watch a demonstration of this exact scenario.

Chaining Vulnerabilities: Reflected XSS + CORS = More Impact!! | Live Demonstration | 2024

The video 'Chaining Vulnerabilities: Reflected XSS + CORS = More Impact!!' from BePractical shows how to chain these two seemingly separate issues into a critical vulnerability.

Watch from 02:02 to 10:50. This is an advanced technique that requires careful observation: Finding the CORS Misconfiguration (02:02 - 05:37): The presenter identifies a sensitive DELETE endpoint and tests its CORS policy. By changing the Origin header to a test subdomain, they confirm that the server allows requests from any subdomain. Finding the XSS Vector (05:37 - 08:12): On a different subdomain, they find a reflected XSS vulnerability. Chaining for Impact (08:12 - 10:50): The final payload is an XSS script injected into the vulnerable subdomain. This script uses XMLHttpRequest to send a DELETE request to the API on the main domain. The browser allows this because of the weak CORS policy, and the victim's account is deleted.

This type of vulnerability chaining is exactly what separates a good bug hunter from an expert. It requires you to see the system as a whole and connect the dots between lower-severity findings to create a high-impact attack.

4. Hands-on Lab: Perform CSRF via XSS

It's time to put your knowledge into practice. This PortSwigger lab challenges you to do exactly what we've covered: use a stored XSS vulnerability to steal a CSRF token and change a victim's email.

Lab: Exploiting XSS to bypass CSRF defenses

This lab is a direct application of today's lesson. You will need to inspect the application, find the CSRF token, and craft a payload to perform an unauthorized action.

Log in to the lab application with the provided credentials (wiener:peter). Analyze the 'Change email' functionality. Use Burp Suite or your browser's developer tools to see what the request looks like and identify the CSRF token. Find the stored XSS vulnerability in the blog comments function. Craft a JavaScript payload that grabs the CSRF token from the 'My account' page and uses it to submit a request to the 'Change email' endpoint. The 'Solution' section provides a complete payload using XMLHttpRequest. Study it carefully. Given your CS background, you should be able to understand how it makes a GET request to fetch the page with the token, parses the response, and then sends the final POST request. Try to build it yourself first!

Conclusion

Excellent work! You have now added another powerful technique to your XSS arsenal. You've learned that even when you can't directly steal a user's HttpOnly cookie, you can still achieve account takeover by commanding their browser to perform actions on their behalf.

Key Takeaways:

  • XSS Bypasses CSRF Protection: An XSS vulnerability negates the protection offered by anti-CSRF tokens because the malicious script runs on the trusted domain.
  • Two-Step Attack Logic: The most common pattern is to first fetch a page to obtain a valid CSRF token and then use that token to forge a second, malicious request.
  • The Right Tool for the Job: Modern payloads use the fetch API or XMLHttpRequest to perform these background requests silently.
  • Impact through Chaining: Combining XSS with other weaknesses, like a misconfigured CORS policy, can drastically increase the impact of your findings.

Next Lesson Preview:
Today, we focused on using XSS to bypass CSRF defenses. This naturally leads to a deeper look at CSRF itself. In the next lesson, you will learn how to test for Cross-Site Request Forgery (CSRF) vulnerabilities as a standalone issue and analyze the effectiveness of different anti-CSRF tokens. This will round out your understanding of session-related attacks.

Can't find a good explanation? Sign up and we'll make it for you

Sign up