Challenge Overview#
- Challenge Name: CSRF vulnerability with no defenses
- Category: Cross-Site Request Forgery (CSRF) / Client-Side Security
- Level: Apprentice
- Target Endpoint:
POST /my-account/change-email - Objective: Exploit a Cross-Site Request Forgery (CSRF) vulnerability lacking defenses to change the victim’s registered email address by hosting an exploit payload on the exploit server and delivering it to the victim.
1. Core Fundamentals#
Cross-Site Request Forgery (CSRF) is a client-side web vulnerability enabling an adversary to induce an authenticated user to perform unintentional, state-changing actions on a trusted web application.
1.1. HTTP Protocol Nature & The Ambient Authority Model#
HTTP is fundamentally a stateless transport protocol. To sustain continuous user authentication across disparate requests, web applications rely on session tokens stored within the client’s browser (typically as HTTP cookies).
The foundational architectural vulnerability enabling CSRF is the browser’s Ambient Authority credential-handling model:
Whenever a web browser initiates an HTTP request targeting a destination origin (whether initiated via hyperlinks, image tags, scripts, or form submissions), it automatically and unconditionally attaches all cookies associated with that domain—regardless of the origin hosting the executing code.
If a server relies exclusively on the presence of the Cookie: session=... header to validate incoming state-changing requests without corroborating user intent or origin, the backend inherently treats cross-site forged transactions as genuine user actions.
| |
1.2. The Same-Origin Policy (SOP) Fallacy#
A prevalent misconception in application security is assuming that the Same-Origin Policy (SOP) inherently protects against CSRF.
- SOP Enforces Read Boundaries: SOP restricts a document or script loaded from origin A (
attacker.com) from reading response data or inspecting the DOM tree of origin B (target.com). - SOP Does Not Enforce Write Boundaries: Standard SOP does not block a web browser from transmitting cross-origin requests. Standard HTML
<form>submissions can target external domains without restriction.
Because CSRF is a one-way, blind state-changing attack, the attacker has no need to read the server’s response. The attack succeeds the moment the server parses the request body and updates backend state. Therefore, SOP provides zero protection against classical form-based CSRF.
1.3. The Three Classical Preconditions for CSRF#
For an application endpoint to be vulnerable to CSRF, three fundamental preconditions must align:
- A Relevant, State-Changing Action: The endpoint executes an action with meaningful business or security implications (such as modifying email addresses, altering passwords, updating billing details, or changing administrative roles).
- Cookie-Based Session Handling: Session management relies strictly on browser cookies transmitted in the request header (
Cookie: session=...). No secondary transport-layer tokens or authorization headers (e.g.,Authorization: Bearer <JWT>) are validated. - Absence of Unpredictable Request Parameters: All parameters required to process the request are deterministic and fully predictable by an external attacker. The application requires no randomized anti-CSRF tokens, dynamic cryptographic nonces, or user verification challenges (such as current password confirmation).
| |
2. Attack Architecture / Threat Model#
2.1. Trust Boundaries & Attack Flow#
The vulnerability arises from a breakdown in client-server trust boundaries:
- The Application Server erroneously trusts that any incoming HTTP request bearing a valid session cookie was intentionally initiated by the user.
- The User’s Browser executes untrusted JavaScript and HTML served by
attacker.comwithin an isolated browsing context, yet transmits ambient credentials belonging totarget.com.
2.2. Attack Flow Diagram#
| |
2.3. Root Cause Analysis#
The root cause of this vulnerability encompasses two distinct engineering failures:
- Lack of Anti-CSRF Token Validation: The endpoint does not implement the Synchronizer Token Pattern. It fails to require a secret, unpredictable, session-bound token with incoming mutation requests.
- Absence of Strict Cookie SameSite Enforcement: The session cookie is issued without modern
SameSite=StrictorSameSite=Laxrestrictions, permitting cross-site form POST requests to transmit authentication cookies without browser intervention.
3. Vulnerability Exploitation#
Phase 1: Baseline Analysis & Traffic Interception via Burp Suite#
We authenticate into the test account (wiener:peter) and trigger the email modification functionality. The traffic is captured via Burp Suite Proxy and analyzed in Burp Suite Repeater:

HTTP Request Analysis#
| |
HTTP Response Analysis#
| |
Attack Surface Evaluation:#
- Target Action Endpoint: The state-changing operation is strictly bound to
/my-account/change-email. Dispatching requests to/my-accountalone will fail because the parent controller does not process mutation parameters. - Authentication Mechanism: The application authenticates the request purely through
Cookie: session=vKteDwKxly5sqly0n4ntPtGPxS8V8KFL. - Absence of CSRF Tokens: Searching for
csrfacross headers and body parameters yields 0 matches. No hidden form tokens exist. - Lack of Re-Authentication: The server does not require verification of the user’s current password prior to committing the email change.
- Immediate Execution: The server returns
302 Found, redirecting back to/my-account?id=wiener. The email address modification is executed synchronously.
Phase 2: Weaponizing the Zero-Click Exploit Payload#
To exploit this vulnerability against external victims, we configure PortSwigger’s Exploit Server (https://exploit-...exploit-server.net/exploit):

We configure the HTTP response parameters on the Exploit Server:
- File:
/exploit - Head:
1 2HTTP/1.1 200 OK Content-Type: text/html; charset=utf-8 - Body:
1 2 3 4 5 6<form action="https://0a3d002503a1b88180f11cbe00b000a8.web-security-academy.net/my-account/change-email" method="POST"> <input type="hidden" name="email" value="hahaha@gmail.com"> </form> <script> document.forms[0].submit(); </script>
Detailed Breakdown of Exploit Mechanics:#
- The
<form>Element:action: Must point to the absolute URL of the vulnerable endpoint (https://0a3d002503a1b88180f11cbe00b000a8.web-security-academy.net/my-account/change-email).method="POST": Instructs the victim browser to dispatch an HTTP POST request formatted asapplication/x-www-form-urlencoded, matching backend expectations.
- The
<input type="hidden">Element:name="email": Corresponds directly to the parameter expected by the server.value="hahaha@gmail.com": The attacker-controlled email address designed to overwrite the victim’s primary contact.type="hidden": Prevents any visual input controls from rendering in the victim’s browser.
- The Programmatic Auto-Submit Mechanism:
document.forms[0]: Accesses the first form node in the DOM tree. Placing this script immediately following the form ensures reliable reference without requiring element identifiers..submit(): Executes the native DOM form submission method immediately upon page load.- Zero-Click Impact: The attack requires zero user interaction beyond simply opening or being redirected to the exploit URL.
Phase 3: Delivering Exploit to Victim & Verification#
- Storing the Payload: Click Store to persist the payload at
/exploit. - Local Sanity Check: Click View exploit to test the exploit against your own active session. Observe that your account email updates to
hahaha@gmail.com. - Delivering to Victim: Click Deliver exploit to victim.

Execution Flow & Lab Resolution:#
The PortSwigger testing infrastructure dispatches a simulated victim bot (authenticated as
wienerin a headless Chromium instance) to access our exploit URL.The victim’s browser evaluates the HTML document, builds the DOM tree, and executes
document.forms[0].submit().Due to the ambient authority model, the victim’s browser includes their active session cookie with the cross-origin POST request directed at the target application.
The target server validates the session cookie, processes the parameter update, and commits
hahaha@gmail.comto the victim’s account.The application detects the state change performed from an external origin, successfully solving the lab:
Banner Status:
LAB Solved— “Congratulations, you solved the lab!” (Confirmed in Figure 3).
4. Remediation Strategies#
Eliminating CSRF vulnerabilities requires a robust, defense-in-depth approach combining cryptographic tokens, browser-level attributes, and workflow verification.
| |
4.1. Primary Defense: Synchronizer Token Pattern (Anti-CSRF Tokens)#
The industry standard defense against CSRF is the Synchronizer Token Pattern:
- When a user authenticates, the server generates a cryptographically strong, pseudorandom token with high entropy (e.g., 256 bits via CSPRNG).
- The server binds this token to the user’s active server-side session.
- When rendering sensitive state-changing forms, the server injects this token into a hidden form parameter:
1 2 3 4 5<form action="/my-account/change-email" method="POST"> <input type="hidden" name="csrf_token" value="c8f1e2d3b4a59687e1f0a2b3c4d5e6f7" /> <input type="email" name="email" value="" required /> <button type="submit">Update email</button> </form> - Upon receiving the POST request, the backend verifies that the submitted
csrf_tokenexactly matches the value stored in the user’s session. - Why this stops CSRF: Under the Same-Origin Policy (SOP), an attacker hosting a malicious site on
attacker.comcannot read the victim’s DOM ontarget.com. Because the attacker cannot obtain or predict this dynamic token, any cross-origin forged request will lack a valid token and will be rejected (403 Forbidden).
Secure Backend Implementation Example (Node.js / Express):#
| |
4.2. Browser-Level Defense: The SameSite Cookie Attribute#
All authentication and session cookies must be explicitly configured with the SameSite attribute:
| |
SameSite=Strict: Cookies are never transmitted in any cross-site request, including top-level link navigations from external sites. Strongly recommended for sensitive user portals and management consoles.SameSite=Lax: Cookies are withheld on cross-site subrequests (such as cross-origin form POSTs, iframes, and image tags). Cookies are only transmitted on safe, top-levelGETnavigations (e.g., following a hyperlink). This prevents form-based CSRF attacks by default.SameSite=None; Secure: Cookies are transmitted in all cross-site contexts. Should only be utilized where cross-site iframe embedding is strictly required, and must be guarded by anti-CSRF tokens.
4.3. Re-Authentication for Sensitive Operations#
For high-impact state changes (such as email changes, password resets, and MFA reconfiguration), require Step-Up Authentication:
- Mandate that the user re-enters their current password or provides a Time-based One-Time Password (TOTP) alongside the new email.
- Because an external attacker executing a CSRF attack cannot guess or extract the victim’s password, the attack fails.
4.4. Modern API Architecture & Custom Request Headers#
For modern Single Page Applications (SPAs) and REST APIs:
- Adopt JSON Payloads: Transition endpoints to expect
Content-Type: application/jsonrather than form-encoded bodies. - Require Custom Headers: Enforce headers such as
X-Requested-With: XMLHttpRequestorX-CSRF-Token. - Leverage CORS Preflight: Browsers cannot send cross-origin requests with custom headers or
application/jsonwithout first dispatching a preflightOPTIONSrequest. Unless the server explicitly authorizes the attacker’s origin viaAccess-Control-Allow-Origin, the browser terminates the request before the state-changing POST is dispatched.
