OWASP lists Custom Request Headers in their CSRF cheat sheet, which says "the client appends a custom header to requests that require CSRF protection" and "the API checks for the existence of this header". It can't be used with native <form>s but I think applications that can benefit from it are common enough.
The Spring Security documentation mentions that "there are known exploits in which headers can be set by another domain" when explaining "why the expected CSRF token is not stored in a cookie by default", but it seems that things has changed now. The OWASP cheat sheet doesn't say it is vulnerable, unlike "Naive Double Submit Cookie" which "remains vulnerable to certain attacks".
So it seems that simply checking for the existence of a custom header set by client-side script is safer than what is currently recommended for SPAs? If so it would be nice if Spring Security provide something like httpSecurity.csrf(csrf -> csrf.customHeader("X-YOURSITE-CSRF-PROTECTION")).
Comment From: sjohnr
@SentretC thanks for reaching out on this issue!
So it seems that simply checking for the existence of a custom header set by client-side script is safer than what is currently recommended for SPAs?
Would you mind elaborating a bit on your thoughts around "what is currently recommended for SPAs"?
I'm wondering which part of the example in the documentation you're specifically comparing to the recommendation in the OWASP cheat sheet. For example, are you thinking about the fact that Spring Security allows a request parameter in addition to a custom header? If so, can you explain what you mean by "checking for the existence of a custom header set by client-side script is safer"?
Comment From: SentretC
The OWASP cheat sheet links to a resource which "provides more information on some vulnerabilities" of the "Naive Double Submit Cookie" method.
If I understand correctly, an application on https://www.example.com following the example configuration provided in the Single-Page Applications section of the Spring Security documentation could be CSRFed if an attacker:
1. Controls http(s)://evil.example.com or MiTMs the victim (HSTS from https://www.example.com doesn't prevent http://evil.example.com)
2. Generates a valid raw-xored token pair
3. Lead the victim to http(s)://evil.example.com which sets the cookie XSRF-TOKEN to the raw token for domain example.com
4. Submit the target request with _csrf=<xored token>
Anyway, it seems that the "Custom Request Headers" approach is no less secure, while at the same time simpler, and don't have the problem of session timeout or multipart upload.
Comment From: sjohnr
Ok, thanks @SentretC. I don't think the information in that OWASP presentation (pdf) is new, but I wanted to ensure I'm understanding your thoughts there. I think we can use this issue to consider the recommendation in OWASP's CSRF cheat sheet. I'll update the title of this issue accordingly.