2

I have a stateless backend and a spa-frontend. Except for the login request, all requests are secured by a jwt in the header.

Additionally the application should now be secured against csrf. Since the backend is stateless, we want to implement double submit tokens. To avoid having to customize every single form in the frontend, we want the token to be submitted as a header instead of a hidden field. We wonder if it makes a difference if the token is generated in the backend or in the frontend.

Right now, we have configured axios to create a new UUID when the application is initialized in the browser. This UUID will be set as a cookies value as well as custom header.

Please note we know all our clients will be "modern" to some extent, so issues with legacy browsers like IE10 are not relevant to us.

We are aware that this mechanism would of course be rendered completely ineffective by an XSS vulnerability.

I have the following understanding:

  • By using the jwt in the header, there is technically already a protection against csrf (according to this answer). Thus, the implementation of the double submit token is only done to satisfy the requirement, but adds no extra security
  • If the double submit token is transmitted via the cookie and the header, it is irrelevant whether the token is created in the client (browser) or in the backend. For the sake of completeness: we use crypto.randomUUID().

Are those statements correct?

5
  • "does it matter where the random key is created?" - Hint: The attacker can also generate random value and double submit it. How should server decide, if particular request was generated by the application or by the attacker?
    – mentallurg
    Commented Apr 17, 2023 at 12:42
  • It is my understanding csrf is an attack where the attacker is using the victims session (=browser context) to forge a request. But for an attacker to be able to generate a new value and to send it (using a custom header) it would be necessary to exploit some kind of scripting-vulnerability. And once the attacker can run custom javascript, you don't need to worry about csrf anymore.
    – samjaf
    Commented Apr 17, 2023 at 13:26
  • No vulnerability needed. Simply said, the attacker offers a button that calls you application. User click on it. Browser sends all cookies to your application, including session ID (if used), JWT (if used as cookie), etc.
    – mentallurg
    Commented Apr 17, 2023 at 13:58
  • Thank you for the explanation and thank you for your time! Isn't the point of the double-submit cookie precisely that the random token is transmitted once via cookie, and a second time in a non-automatic way (in our case as a custom header)? As I understand it, exactly the attack you describe is averted, because in this scenario the attacker has no chance to set the token as a custom header. Please elaborate, if I misunderstood you or if I'm overseeing something.
    – samjaf
    Commented Apr 18, 2023 at 6:42
  • Correct. For AJAX it is sufficient to set a header, But if there is an HTML form, you cannot set any header.
    – mentallurg
    Commented Apr 22, 2023 at 1:22

2 Answers 2

1

It doesn't matter that much, as an attacker doesn't need to figure out the value of the anit-csrf token to perform a successful attack. The conditions that make a CSRF attack possible in a stateless application are the following:

  1. The attacker knows the request format the targeted website accepts.
  2. The attacker can trick the user into unintentionally make a request to the website.

The way a double submit cookie makes it safer is by requiring an anti-csrf token to be sent both as cookie and as a request parameter (or header). In that scenario, even if the attacker tricks the user into making a request, only the cookie (if previously set) will be automatically sent, as the attacker will be unable to predict the value that should've been double-submitted as a request parameter.

That being said: bear in mind that attackers have access to the frontend source code, if the anti-csrf token is generated on the fornend using an algorithm that is not cryptographically safe, the attacker may be able to guess the value that will be sent as the cookie and double-submit it, bypassing the protection.

Additionally, I recommend reading this question.

1

JSON Web Tokens by themselves do not prevent cross-site request forgery attacks. It depends on how exactly the tokens are transmitted. If there's any chance that the token might be automatically submitted by the browser in a cross-origin request, then CSRF attacks are possible. This is the case for e. g.Authorization: Basic headers. JWTs are typically sent in a Authorization: Bearer header, and I'm not aware of any standard browser which saves and submits bearer tokens. However, I'm also not aware that the CORS (or Fetch) specification explicitly forbids Authorization: Bearer headers for cross-origin requests, so the CSRF protection is more of a happy coincidence rather than by design.

If you want to be sure, then include a token -- either the JWT or a dedicated anti-CSRF token -- in a custom header which will never be automatically submitted by the browser, e. g. X-Anti-CSRF-Token.

Whether the anti-CSRF token is generated by the client or the server doesn't matter.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .