Web Security

CSRF (Cross-Site Request Forgery)

About 3 min read

What Is CSRF (Cross-Site Request Forgery)

CSRF (Cross-Site Request Forgery) is an attack technique that causes a user's browser to send unintended requests to a web site where the user is already authenticated. The attacker prepares a trap web page or email, and the moment the victim views it, a malicious request is automatically sent from the victim's browser to the target site.

Browsers automatically attach cookies that belong to the destination domain regardless of which page the request originated from, so if the victim is logged in, the attacker's request is processed as authenticated. Operations that change state - such as password changes, money transfers, email address changes, and purchases - become targets of the attack.

How the Attack Works with Examples

A CSRF attack is executed in the following flow.

  1. The victim logs into the target site (e.g., online banking), and a session cookie is stored in the browser
  2. The victim views a trap page prepared by the attacker (via an email link, forum post, etc.)
  3. HTML or JavaScript embedded in the trap page sends a request from the victim's browser to the target site
  4. The browser automatically attaches the session cookie, so the target site processes it as a legitimate request

For example, if a transfer function is designed so that POST /transfer takes the recipient and the amount from the request body, the attacker only needs to embed an auto-submitting form in the trap page to execute a transfer from the victim's account. If the form is placed in an off-screen iframe and submitted with JavaScript, the victim never notices that the operation happened.

While often confused with XSS, CSRF is fundamentally different in that it forges legitimate requests from the victim's browser rather than executing the attacker's script in the victim's browser.

Implementing Defenses

The core of CSRF defense is implementing mechanisms that verify whether a request is based on the legitimate user's intent.

CSRF Tokens

The server generates a random token when displaying a form and embeds it in a hidden field. When the form is submitted, the server verifies that the token matches, rejecting forged requests from external sites. This approach is called the Synchronizer Token Pattern: the token is unique per session, and the same-origin policy keeps JavaScript on external sites from reading it. If XSS exists, however, the token itself can be stolen, so CSRF tokens only work when combined with XSS countermeasures. When you do not want to hold tokens on the server, the double-submit cookie pattern, which places a signed value in both a cookie and the request and compares the two, is an alternative.

SameSite Cookie Attribute

Setting the SameSite attribute on cookies controls whether cookies are attached to cross-site requests.

  • SameSite=Strict: Does not attach cookies to any requests from external sites. Most secure, but login state is not maintained when accessing via external links
  • SameSite=Lax: Attaches cookies only to GET requests from top-level navigation (link clicks). Since cookies are not attached to POST requests, most CSRF attacks are prevented. When the attribute is unspecified and Lax is applied as the default, however, a more permissive version is used and cookies are attached to POST requests made within two minutes of the cookie being set
  • SameSite=None: Attaches cookies to cross-site requests as well. Must be used with the Secure attribute

The SameSite attribute is effective as defense in depth, but it is not a CSRF countermeasure on its own. Same-site is judged at the registrable domain level, so a cookie issued by app.example.com is treated as same-site even for requests from other.example.com, which turns a hijacked subdomain or third-party content on a shared domain into a bypass. Cookies that have to specify SameSite=None for external service integration also remain, as do older browsers and embedded browsers where the default is not applied, so always combine SameSite with token verification.

Other Countermeasures

  • Origin / Referer header verification: Confirm that the request origin is your own site. However, the Referer may not be sent due to privacy settings or proxies
  • Requiring custom headers: HTML forms cannot add arbitrary headers, so requiring a custom header such as X-Requested-With rejects forged requests sent through forms. Adding such a header from cross-site JavaScript requires a CORS preflight, but this defense does not hold if you widen the allowed origins while Access-Control-Allow-Credentials is enabled, so keep the allowlist as narrow as possible
  • Dividing roles with security headers: CSP and X-Frame-Options are not mechanisms that stop CSRF itself. Defend against CSRF with cookie attachment conditions and request origin verification, and design security headers as the means of closing the separate paths of XSS and clickjacking

Built-in CSRF Protection in Frameworks

Many server-side web frameworks provide built-in CSRF protection.

  • Django: CsrfViewMiddleware is enabled by default and verifies the token that the {% csrf_token %} template tag embeds. Over HTTPS it also checks the Origin header against CSRF_TRUSTED_ORIGINS, which covers attacks that come through subdomains
  • Ruby on Rails: In newly created applications config.action_controller.default_protect_from_forgery is enabled, so CSRF tokens are generated and verified automatically. To set it explicitly, write protect_from_forgery with: :exception
  • Spring Security: CSRF protection applies by default to unsafe HTTP methods such as POST. When you use the Thymeleaf or JSP integration, CsrfToken is inserted into forms automatically
  • Next.js / SPA: For API routes that use cookie authentication, combine SameSite cookies with Origin header verification. Consider additional protection with a WAF

If you disable a framework's CSRF protection, verify that alternative countermeasures are reliably implemented. When excluding CSRF protection for API endpoints, the prerequisite is switching to Bearer Token authentication and not using cookie-based authentication.

To learn more about this topic, see HTTP Security Headers: 5 Essential Headers to Protect Your Website.

Common Misconceptions

CSRF cannot occur with GET requests
If state-changing operations (deletion, settings changes, etc.) are implemented via GET requests, they become CSRF targets. A GET request can be sent simply by setting a URL in an img tag's src attribute, so state changes should always be implemented with POST/PUT/DELETE. Even after <code>SameSite=Lax</code> became the default, Lax lets GET through as a safe method, so implementations that change state via GET are not protected by the browser default.
Using HTTPS prevents CSRF
HTTPS provides communication encryption and tamper prevention but is unrelated to CSRF. CSRF sends legitimate requests from the legitimate user's browser, so the attack succeeds even when communication is encrypted.
Share

Related Terms

Related Articles