// FIXME: Add links to Servlet and WebFlux support
[[csrf]]
= Cross Site Request Forgery (CSRF)
Spring provides comprehensive support for protecting against https://en.wikipedia.org/wiki/Cross-site_request_forgery[Cross Site Request Forgery (CSRF)] attacks.
See the relevant sections for specific information on CSRF protection for xref:servlet/exploits/csrf.adoc#servlet-csrf[servlet] and xref:reactive/exploits/csrf.adoc#webflux-csrf[WebFlux] based applications.
Furthermore, it could just as easily happen when visiting an honest site that is a victim of a https://www.owasp.org/index.php/Cross-site_Scripting_(XSS)[XSS attack].
So how do we protect our users from such attacks?
[[csrf-protection]]
== Protecting Against CSRF Attacks
The reason that a CSRF attack is possible is that the HTTP request from the victim's website and the request from the attacker's website are exactly the same.
This means there is no way to reject requests coming from the evil website and allow only requests coming from the bank's website.
To protect against CSRF attacks, we need to ensure there is something in the request that the evil site is unable to provide so we can differentiate the two requests.
For <<csrf-protection,either protection>> against CSRF to work, the application must ensure that https://tools.ietf.org/html/rfc7231#section-4.2.1["safe" HTTP methods are idempotent].
This means that requests with the HTTP `GET`, `HEAD`, `OPTIONS`, and `TRACE` methods should not change the state of the application.
The predominant and most comprehensive way to protect against CSRF attacks is to use the https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html#synchronizer-token-pattern[Synchronizer Token Pattern].
This solution is to ensure that each HTTP request requires, in addition to our session cookie, a secure random generated value called a CSRF token be present in the HTTP request.
You will notice that the HTTP request now contains the `_csrf` parameter with a secure random value.
The evil website will not be able to provide the correct value for the `_csrf` parameter (which must be explicitly provided on the evil website) and the transfer will fail when the server compares the actual CSRF token to the expected CSRF token.
[[csrf-protection-ssa]]
=== SameSite Attribute
An emerging way to protect against <<csrf,CSRF Attacks>> is to specify the https://tools.ietf.org/html/draft-west-first-party-cookies[SameSite Attribute] on cookies.
A server can specify the `SameSite` attribute when setting a cookie to indicate that the cookie should not be sent when coming from external sites.
[NOTE]
====
Spring Security does not directly control the creation of the session cookie, so it does not provide support for the SameSite attribute.
Spring Framework's https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/server/session/CookieWebSessionIdResolver.html[`CookieWebSessionIdResolver`] provides out of the box support for the `SameSite` attribute in WebFlux-based applications.
* `Strict`: When specified, any request coming from the https://tools.ietf.org/html/draft-west-first-party-cookies-07#section-2.1[same-site] includes the cookie.
Otherwise, the cookie is not included in the HTTP request.
* `Lax`: When specified, cookies are sent when coming from the https://tools.ietf.org/html/draft-west-first-party-cookies-07#section-2.1[same-site] or when the request comes from top-level navigations and the <<Safe Methods Must be Idempotent,method is idempotent>>.
Otherwise, the cookie is not included in the HTTP request.
With the `SameSite` attribute set on our session cookie, the browser continues to send the `JSESSIONID` cookie with requests coming from the banking website.
However, the browser no longer sends the `JSESSIONID` cookie with a transfer request coming from the evil website.
There are some important https://tools.ietf.org/html/draft-west-first-party-cookies-07#section-5[considerations] to be aware of when using `SameSite` attribute to protect against CSRF attacks.
We could improve the protection and usability of `SameSite` protection against CSRF attacks by implementing https://github.com/spring-projects/spring-security/issues/7537[gh-7537].
A common question is "`do I need to protect JSON requests made by JavaScript?`"
The short answer is: It depends.
However, you must be very careful, as there are CSRF exploits that can impact JSON requests.
For example, a malicious user can create a http://blog.opensecurityresearch.com/2012/02/json-csrf-with-parameter-padding.html[CSRF with JSON by using the following form]:
If an application were not validating the `Content-Type` header, it would be exposed to this exploit.
Depending on the setup, a Spring MVC application that validates the Content-Type could still be exploited by updating the URL suffix to end with `.json`, as follows:
For example, consider an application that uses a custom cookie that contains all the state within it for authentication (instead of the JSESSIONID).
When the CSRF attack is made, the custom cookie is sent with the request in the same manner that the JSESSIONID cookie was sent in our previous example.
The application is vulnerable since the browser automatically includes the username and password in any requests in the same manner that the JSESSIONID cookie was sent in our previous example.
To protect against https://en.wikipedia.org/wiki/Cross-site_request_forgery#Forging_login_requests[forging login requests], the login HTTP request should be protected against CSRF attacks.
Protecting against forging login requests is necessary so that a malicious user cannot read a victim's sensitive information.
. The malicious user then tricks the victim into visiting the compromised website and entering sensitive information.
. The information is associated to the malicious user's account so the malicious user can log in with their own credentials and view the victim's sensitive information.
A possible complication to ensuring login HTTP requests are protected against CSRF attacks is that the user might experience a session timeout that causes the request to be rejected.
A session timeout is surprising to users who do not expect to need to have a session to log in.
A possible complication to ensuring logout HTTP requests are protected against CSRF attacks is that the user might experience a session timeout that causes the request to be rejected.
A session timeout is surprising to users who do not expect to have a session to log out.
For more information, see <<csrf-considerations-timeouts>>.
This is the same reason Ruby on Rails https://weblog.rubyonrails.org/2011/2/8/csrf-protection-bypass-in-ruby-on-rails/[no longer skips a CSRF checks when the header X-Requested-With is present].
See https://web.archive.org/web/20210221120355/https://lists.webappsec.org/pipermail/websecurity_lists.webappsec.org/2011-February/007533.html[this webappsec.org thread] for details on how to perform the exploit.
Before you integrate Spring Security's CSRF protection with multipart file upload, you should first ensure that you can upload without the CSRF protection.
More information about using multipart forms with Spring, see the https://docs.spring.io/spring/docs/5.2.x/spring-framework-reference/web.html#mvc-multipart[1.1.11. Multipart Resolver] section of the Spring reference and the https://docs.spring.io/spring/docs/5.2.x/javadoc-api/org/springframework/web/multipart/support/MultipartFilter.html[`MultipartFilter` Javadoc].
If letting unauthorized users upload temporary files is not acceptable, an alternative is to include the expected CSRF token as a query parameter in the action attribute of the form.
You can find additional information in https://www.w3.org/Protocols/rfc2616/rfc2616-sec15.html#sec15.1.3[RFC 2616 Section 15.1.3 Encoding Sensitive Information in URI's].