Challenge Overview#
- Challenge Name: CSRF where token validation depends on request method
- Category: Cross-Site Request Forgery (CSRF) / Client-Side Security
- Level: Apprentice
- Target Endpoint:
POST /my-account/change-email - Objective: Exploit a flawed anti-CSRF token implementation that only validates tokens on
POSTrequests by converting the request toGETto change the victim’s email address via the exploit server.
1. Core Fundamentals#
1.1. Anti-CSRF Token Architecture (Synchronizer Token Pattern)#
In modern web applications, the primary cryptographic defense against Cross-Site Request Forgery is the Anti-CSRF Token (Synchronizer Token Pattern):
- When a user authenticates, the server generates a cryptographically strong, pseudorandom token bound to the user’s active session.
- The server embeds this token into sensitive state-changing HTML forms (or passes it through custom HTTP headers).
- Upon receiving a mutation request, the server compares the submitted token against the session token.
- Because the browser’s Same-Origin Policy (SOP) prevents external, untrusted origins from reading the victim’s DOM on the target domain, an adversary cannot steal or guess this token to forge a legitimate request.
1.2. The Ambient Authority Model & Automatic Cookie Transmission#
Under the browser’s Ambient Authority credential-handling model, whenever a web browser initiates an HTTP request to a target origin, it automatically attaches all stored cookies matching that domain.
Without anti-CSRF tokens or strict SameSite cookie enforcement, the target web server cannot distinguish whether the request was intentionally dispatched by the user or triggered by malicious script running on an external origin.
1.3. The Architectural Flaw: Conditional Middleware Validation#
The vulnerability in this scenario does not stem from weak cryptography or token leakage; rather, it originates from defective enforcement logic in the authentication/authorization filter pipeline.
Many web developers operate under the flawed assumption that CSRF is exclusively a POST-based vulnerability:
“Since web forms that mutate database records submit data via POST, we only need to inspect CSRF tokens when
request.method === 'POST'.”
Consequently, security middleware is written conditionally:
| |
1.4. HTTP Semantics & RFC Violation#
According to RFC 7231 / RFC 9110 (HTTP Semantics):
GETrequests are formally designated as Safe and Idempotent.- Safe methods are intended solely for information retrieval and must never alter server state.
- Allowing an account modification action (such as an email update) to execute via an HTTP
GETrequest violates standard protocol specifications and exposes the application to method-swapping bypasses.
1.5. The Three Classical Preconditions for CSRF#
| |
2. Attack Architecture / Threat Model#
2.1. Trust Boundaries & Controller Ambiguity#
The vulnerability materializes when the underlying controller or routing engine is loosely typed with respect to HTTP verbs and parameter sources:
- Universal Parameter Binding: Frameworks such as PHP (via
$_REQUEST), legacy Spring controllers using generic@RequestMapping, or Express.js routes extract parameters indistinctly from either the URL query string (req.query) or the request body (req.body). - Multi-Verb Handling: If a state-changing route listens on multiple HTTP verbs (or fails to explicitly restrict incoming traffic to
POST), an attacker can simply pivot the HTTP method fromPOSTtoGET. The security middleware skips token verification, while the business logic controller ingests the parameters from the query string and commits the database mutation.
2.2. Attack Flow Diagram#
| |
2.3. Root Cause Analysis#
The root cause comprises two distinct architectural defects:
- Conditional Security Enforcement: Anti-CSRF verification logic is coupled strictly to the HTTP method (
POST) rather than the state-changing nature of the resource. - Permissive Route Handling: The backend endpoint accepts mutating parameters via
GETrequests, failing to enforce RESTful method constraints (HTTP 405 Method Not Allowed).
3. Vulnerability Exploitation#
Phase 1: Baseline Request Interception & Traffic Inspection#
We log 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#
| |
Observations:#
- The application issues a standard
POSTrequest containing two parameters:emailandcsrf. - The server responds with
HTTP/2 302 Found(redirecting to/my-account?id=wiener), verifying that the email was successfully changed tohihi@gmail.com. - At first glance, the application appears properly defended because a Synchronizer Token is present.
Phase 2: Proving Token Validation on POST Requests#
To determine whether the server actively validates the token or merely treats it as an unvalidated parameter, we send the request to Burp Repeater, remove the &csrf=... parameter, and re-send the request:

| |
Server Response:#
| |
Security Takeaway:#
The server actively rejects the request with 400 Bad Request and an explicit error payload: "Missing parameter 'csrf'". This confirms that when the method is POST, the CSRF validation filter is functional and mandatory.
Phase 3: Method Swapping & Token Bypass in Repeater#
Next, we test for HTTP Method Confusion / Method-Dependent Validation:
- In Burp Repeater, right-click the request and select Change request method (or manually convert the HTTP verb from
POSTtoGET). - Move the
emailparameter to the URL query string and omit thecsrfparameter entirely.

| |
Server Response:#
| |
Critical Finding:#
The server returns HTTP/2 302 Found instead of an error. The CSRF validation filter was bypassed entirely simply by converting the HTTP verb to GET.
Phase 4: UI Verification of State Modification#
To verify that the database update was committed on the server, we refresh the victim’s account dashboard in the browser:

As confirmed in Figure 4:
- Username:
wiener - Email:
haha@gmail.com
The database mutation succeeded without requiring an anti-CSRF token.
Phase 5: Weaponizing the Exploit on the Exploit Server#
We now craft the weaponized payload on the PortSwigger Exploit Server (https://exploit-...exploit-server.net/exploit):

Payload Configuration:#
- File:
/exploit - Head:
1 2HTTP/1.1 200 OK Content-Type: text/html; charset=utf-8 - Body:
1 2 3 4 5 6<form method="GET" action="https://0a1500f604f48afd809a035e000f002c.web-security-academy.net/my-account/change-email"> <input type="hidden" name="email" value="hacking@gmail.com"> </form> <script> document.forms[0].submit(); </script>
Detailed Breakdown of Exploit Mechanics:#
method="GET": Instructs the browser to serialize form inputs into URL query parameters upon submission, producing a request to:1https://0a1500f604f48afd809a035e000f002c.web-security-academy.net/my-account/change-email?email=hacking%40gmail.com<input type="hidden">: Conceals input fields from the victim’s display, ensuring the exploit executes stealthily.document.forms[0].submit(): Automatically submits the form immediately upon DOM parsing, providing Zero-Click execution.
Zero-Scripting Alternative:
Because the endpoint permits state mutations via GET, an attacker does not even require JavaScript! A simple HTML image tag achieves the exact same result:
| |
Phase 6: Delivering Exploit to Victim & Verification#
- Click Store to persist the payload on the Exploit Server.
- Click Deliver exploit to victim.

Execution Flow & Lab Resolution:#
- The PortSwigger automated victim crawler visits
/exploitwhile logged into an active session aswiener. - The bot’s browser loads the page and evaluates
document.forms[0].submit(). - A cross-site
GETrequest is fired towards/my-account/change-email?email=hacking@gmail.com. - The browser automatically attaches the victim’s session cookie (
Cookie: session=...). - The backend CSRF filter sees that the request method is
GETand skips token validation. - The account controller processes the query parameter and updates the victim’s email to
hacking@gmail.com. - The lab engine detects the state change on the simulated victim account and marks the challenge as Solved (Figure 6).
4. Remediation Strategies#
Remediating method-dependent CSRF flaws requires defense-in-depth across routing semantics, middleware validation, and cookie attributes.
| |
4.1. Strict HTTP Method Enforcement (REST Semantics)#
State-changing endpoints must strictly reject any HTTP verb other than POST, PUT, PATCH, or DELETE:
- Spring Boot (Java):
1 2 3 4 5// INSECURE: Accepts any HTTP method @RequestMapping("/my-account/change-email") // SECURE: Strictly accepts only POST @PostMapping("/my-account/change-email") - Express.js (Node.js):
1 2 3// INSECURE: router.all(...) or app.use(...) // SECURE: app.post('/my-account/change-email', csrfProtection, changeEmailHandler); - If a client issues an unsupported HTTP method (such as
GET), the server must reject it immediately:1 2HTTP/1.1 405 Method Not Allowed Allow: POST
4.2. Method-Agnostic Anti-CSRF Token Validation#
CSRF protection filters should never make trust assumptions based purely on the HTTP method if that endpoint is capable of changing state:
- Ensure security filters inspect tokens on all mutating actions, regardless of how the request was packaged.
- If a framework uses global CSRF protection (e.g., Spring Security, Django, Laravel), avoid exempting
GETroutes from validation if those routes perform database writes.
4.3. Strict Separation of Query Parameters and Body Payloads#
Never use catch-all parameter extraction methods (such as PHP’s $_REQUEST or generic helper functions that fall back to query strings):
- Read mutation parameters strictly from the request body:
1 2 3 4 5 6 7 8 9// INSECURE: Accepts input from $_GET or $_POST indistinctly $email = $_REQUEST['email']; // SECURE: Strictly enforce POST method and read from $_POST if ($_SERVER['REQUEST_METHOD'] !== 'POST') { http_response_code(405); exit('Method Not Allowed'); } $email = $_POST['email'];
4.4. Enforcing SameSite Cookie Attributes#
Configure session cookies with the SameSite attribute:
| |
- Critical Note on GET Vulnerabilities: Under standard
SameSite=Lax, cookies are still transmitted on top-level navigations viaGET(e.g., clicking a link). This means that if an application allows state changes viaGET, an attacker can still execute CSRF via a simple link or redirect. - Enforcing
POSTalongsideSameSite=Laxensures that cross-site form submissions are blocked by the browser.
4.5. Mandatory Step-Up Re-Authentication#
Require users to confirm their current password or submit a Multi-Factor Authentication (MFA) OTP whenever updating critical account attributes (email, password, phone number). Because an attacker cannot guess or forge the victim’s secret credentials, CSRF attacks become unfeasible.
