Skip to content

CSRF Detection

5 min read Created Sep 13, 2026 Last updated Sep 13, 2026

Cross-Site Request Forgery forces a victim's browser to send authenticated requests to a target application without the user's knowledge. If the application relies solely on cookies for authentication and does not validate request origin, any page the victim visits can trigger state-changing actions on their behalf. Detection confirms the application is missing or improperly validating anti-CSRF protections. Confirmed CSRF moves to CSRF exploitation.

  • Missing CSRF tokens in forms and POST requests indicate no anti-forgery protection is in place.
  • Token validation failures reveal whether the server actually checks the token value, or just checks for its presence.
  • SameSite cookie analysis determines if browser-level protections block cross-origin cookie submission.
  • Referer and Origin header checks test whether the server validates the request source as a fallback defense.

Identifying Missing CSRF Tokens

Start by inspecting HTML forms for hidden token fields. Fetch the page and look for hidden inputs with names like csrf, _token, csrfmiddlewaretoken, or authenticity_token. If no such field exists, the form has no CSRF protection at all.

┌──(kali㉿kali)-[~]
└─$ curl -sk https://$DOMAIN/account/settings | grep -iP 'csrf|_token|authenticity'
Explain command
-sk Silent mode with TLS verification skipped.
grep -iP 'csrf|_token|authenticity' Case-insensitive search for common CSRF token field names in the HTML response.

An empty response means no token field was found in the HTML. Check the POST request itself to confirm no token is submitted as a parameter or custom header. Intercept the request in Burp or replay it with curl and inspect the body parameters.

┌──(kali㉿kali)-[~]
└─$ curl -sk -X POST https://$DOMAIN/account/settings -H 'Cookie: session=abc123' -d 'email=test@attacker.com' -v 2>&1 | grep -iE '< HTTP|csrf|_token'
< HTTP/2 302

A 302 redirect on the POST without any token parameter in the request body confirms the action succeeded without CSRF protection. If the response is a 403 or 422 with a "token missing" message, the application does enforce token validation.

Testing Token Validation

When a CSRF token is present, test whether the server actually validates it. Many implementations check only that the parameter exists, not that the value is correct. Run four tests against the same state-changing endpoint.

┌──(kali㉿kali)-[~]
└─$ curl -sk -X POST https://$DOMAIN/account/settings -H 'Cookie: session=abc123' -d 'email=test@attacker.com'
┌──(kali㉿kali)-[~]
└─$ curl -sk -X POST https://$DOMAIN/account/settings -H 'Cookie: session=abc123' -d 'email=test@attacker.com&_token=AAAAAAAAAA'
┌──(kali㉿kali)-[~]
└─$ curl -sk -X POST https://$DOMAIN/account/settings -H 'Cookie: session=abc123' -d 'email=test@attacker.com&_token='
┌──(kali㉿kali)-[~]
└─$ curl -sk -X POST https://$DOMAIN/account/settings -H 'Cookie: session=abc123' -d 'email=test@attacker.com&_token=TOKEN_FROM_ATTACKER_SESSION'

If any of these requests succeed (200 or 302 to a success page), the token validation is broken. The most common failure is accepting tokens from other sessions, which means tokens are not tied to the user's session. Applications that only check for the parameter's presence (not its value) will accept an empty or garbage token. Both cases are exploitable.

Modern browsers default to SameSite=Lax for cookies that do not explicitly set the attribute. This blocks cross-origin POST requests from sending the cookie, which prevents most CSRF attacks even without tokens. Check the session cookie's Set-Cookie header to determine the effective SameSite policy.

┌──(kali㉿kali)-[~]
└─$ curl -skI https://$DOMAIN/login -X POST -d 'user=test&pass=test' | grep -i 'set-cookie'
set-cookie: session=xyz789; Path=/; HttpOnly; Secure; SameSite=None

Interpret the result based on the SameSite value:

  • SameSite=None with Secure: cookies are sent on all cross-origin requests. CSRF is fully possible if no other protection exists.
  • SameSite=Lax (or absent, which defaults to Lax in Chrome and Firefox): cookies are sent only on top-level GET navigations from external sites. POST-based CSRF is blocked, but GET-based state-changing actions remain vulnerable.
  • SameSite=Strict: cookies are never sent on any cross-origin request. CSRF through direct cross-origin requests is blocked entirely.

Even with SameSite=Lax, GET-based CSRF still works. If the application processes state changes via GET parameters (password reset links, email change via URL), those are exploitable through image tags, link clicks, and top-level redirects. Focus on finding GET endpoints that perform actions when Lax is in effect.

Referer and Origin Header Checks

Some applications validate the Referer or Origin header as a CSRF defense instead of tokens. Test whether the server rejects requests with a missing or incorrect origin.

┌──(kali㉿kali)-[~]
└─$ curl -sk -X POST https://$DOMAIN/account/settings -H 'Cookie: session=abc123' -H 'Origin: https://attacker.com' -d 'email=test@attacker.com&_token=VALID_TOKEN'
┌──(kali㉿kali)-[~]
└─$ curl -sk -X POST https://$DOMAIN/account/settings -H 'Cookie: session=abc123' -d 'email=test@attacker.com&_token=VALID_TOKEN'

If the request succeeds with a foreign Origin or without a Referer, the header-based validation is absent or bypassable. Even when the server does check the Referer, an attacker can suppress it entirely by adding a referrer policy to the exploit page:

<meta name="referrer" content="no-referrer">

This causes the browser to omit the Referer header entirely. Applications that accept requests with a missing Referer (rather than rejecting them) are vulnerable. A strict implementation should reject any request without a valid Referer from the expected origin.

References