Cross-Site Request Forgery (CSRF)
Overview
Cross-site request forgery (CSRF) is a vulnerability that allows an attacker to induce users to perform actions that they do not intend to perform.
For example, consider an application that allows a user to change their email address by making the following HTTP request:
In this case, an attacker can construct a web page containing the following HTML:
If a victim visits this page, the following will happen:
The attacker's page will trigger an HTTP request to the vulnerable website.
If a user is logged in to the vulnerable website, their browser will automatically include their session cookie in the request (assuming
SameSite
cookies are not being used).The vulnerable website will process the request in the normal way, treat it as having been made by a victim, and change their email address.
As a result, an attacker's email will be linked to the victim's account.
You can find more details at PortSwigger Web Security Academy: Cross-site request forgery (CSRF).
This page describes various Cross-Site Request Forgery (CSRF) attack protection schemes and recommendations for implementing them.
General
Use the built-in CSRF protection in the used framework. Make sure the configuration of the built-in CSRF protection meets the requirement described in the Base mitigations section.
If your framework does not have built-in CSRF protection, implement token-based CSRF protection, see the Base mitigations section.
Log CSRF failures, see the Logging and Monitoring page.
Comply with requirements from the Error and Exception Handling page.
Comply with requirements from the Sensitive Data Management page.
Implement at least one advanced mitigation, see the Advanced mitigations section.
Base mitigations
This section describes CSRF protections based on a token that a client passes to a server when making a request.
General
Validate a CSRF token for each request with unsafe HTTP methods:
POST
,PUT
,DELETE
,PATCH
.Reject the request if a CSRF token fails validation.
Use CSRF tokens of length 16+ bytes.
Synchronizer token (Statefull)
Synchronizer token is an approach to implementing CSRF protection that requires storing a token on a server side.
Approach description:
At the start of a session, a CSRF token is generated on the server side.
The token is stored on the server side for later verification.
In response to an authentication request (session start), the token is returned to a client:
The token can be returned inside HTML, for example as a hidden form field or inside the
<meta>
tag.The token may be returned in an HTTP header, such as
X-CSRF-Token
.
Subsequent requests from a client must contain the CSRF token:
The token can be transmitted to a server within a request body.
The token can be transmitted to a server in an HTTP header, such as
X-CSRF-Token
, using an XHR request.
The server side checks for the identity of the token stored on the server side and the token sent by a client.
Use a cryptographically strong generator to generate a CSRF token, see the Cryptography: Random Generators page.
Generate a unique CSRF token for each user session.
Sent a CSRF token in a request body or a custom header. Do not use cookies or URL parameters to transmit CSRF tokens.
Sent a CSRF token in the custom HTTP request header that is inserted via JavaScript.
Double-submit cookie (Stateless)
Double submit cookie is an approach to implement CSRF protection that does not require storing tokens on the server side.
Approach description:
A CSRF token is generated on the server side when a client performs a request.
In response to the request, the server-side returns the token in two places:
Cookies.
One of the response parameters.
Subsequent requests from a client must contain both CSRF tokens received earlier:
Cookies.
Inside the body or in the HTTP header.
The server side checks for the identity of the token from cookies and the token from the body or HTTP header.
Use this approach only if you are sure that:
All subdomains are under your control.
All subdomains have the same protection level.
All requests go exclusively over HTTPS.
Use a cryptographically strong generator to generate a CSRF token, see the Cryptography: Random Generators page.
Generate a new CSRF token for each request.
Store a CSRF token in the
ultimate
cookie, see the Cookie Security page.The lifetime of a cookie with a CSRF token ~ 30 minutes, see the
Expires
andMax-Age
cookie attributes in the Cookie Security page.
HMAC-based token (Stateless)
The HMAC-based token is an approach to implement CSRF protection that does not require storing tokens on the server side. In this case, the token is data hashed using HMAC.
Approach description:
A token is generated on the backend when a client performs a request:
In response to the request, the server side returns the generated token:
The token can be given inside HTML, for example as a hidden form field or inside the
<meta>
attribute.The token may be given in an HTTP header, such as
X-CSRF-Token
.
Subsequent requests from a client must contain the CSRF token received earlier:
The token can be passed to the backend inside a body.
The token can be passed to the backend in an HTTP header, such as
X-CSRF-Token
, via an XHR request.
The server side generates a token based on at least the user ID and timestamp and checks for the identity of the generated token with the token from the client.
Use HMAC to generate CSRF tokens. Use at least the following data for the CSRF token generation:
User ID.
Timestamp.
Do not use cookies to transmit CSRF tokens.
Generate a new CSRF token for each request.
Set the lifetime of a CSRF token ~ 30 minutes.
Comply with the requirements from the Cryptography: Hash-based Message Authentication Code (HMAC) page.
Encryption-based token (Stateless)
The encryption-based token is an approach to implement CSRF protection that does not require storing tokens on the server side. In this case, the token is encrypted data.
Approach description:
A token is generated on the server side when a client performs a request:
In response to the request, the server side returns the generated token:
The token can be given inside HTML, for example as a hidden form field or inside the
<meta>
attribute.The token may be given in an HTTP header, such as
X-CSRF-Token
.
Subsequent requests from a client must contain the CSRF token received earlier:
The token can be passed to the backend inside a body.
The token can be passed to the backend in an HTTP header, such as
X-CSRF-Token
, via an XHR request.
The server side decrypts the received token and compares the stored data (at least user ID and timestamp) with the expected data.
Use encryption to generate CSRF tokens. Use at least the following data for the CSRF token generation:
User ID.
Timestamp.
Do not use cookies to transmit CSRF tokens.
Generate a new CSRF token for each request.
Set the lifetime of a CSRF token ~ 30 minutes.
Comply with the requirements from the Cryptography: Encryption page.
Advanced mitigations
Advanced CSRF protection mechanisms. Use these mechanisms as an additional layer of protection to the mechanisms described in the Base Mitigations section.
Store a session token in the
ultimate
cookie, see the Cookie Security page.Require user interaction for highly sensitive operations:
Require a user to re-authenticate.
Require multi-factor authentication.
Use CAPTCHA.
CSRF protection implementation
Use the github.com/gorilla/csrf package to implement CSRF protection.
github.com/gorilla/csrf implements the double-submit cookie approach. Make sure the requirements for the Double-submit cookie (Stateless) section are met.
References
Last updated