1

Note: I have read the answer to this question, but found it unsatisfactory, probably because I don't understand enough about security.

I'm referring to a frontend server-side rendered SPA + a backend API, which needs to use cookies, and needs persistent login. Since I need cookies for server-side authentication, I want to eliminate any usage of LocalStorage for authentication (to (further) mitigate XSS)

  1. Upon successful login, an httpOnly cookie is set by backend, auth_token, and is sent back to the client's browser. This contains the authentication token. It will be sent automatically with each request (as is every cookie).

  2. Another cookie is set by backend, csrftoken, which is a long random string.

  3. The frontend application (a JS framework) does NOT refer, store, or save auth_token anywhere in its code.

  4. The frontend application code checks to see if there's a csrftoken cookie present, and if there is, attaches it as a custom header, X-CSRFToken, with the same value as csrftoken.

  5. The server authenticates a user successfully if:

    5.1 auth_token present and valid (database token)

    5.2 csrftoken cookie + X-CSRFToken header are present and not empty

    5.3 csrftoken cookie + X-CSRFTokenare equal

Here's my question: What's the difference between having csrftoken (and therefore the X-CSRFToken header) as a very long, random string, and something like 1? It is clearly stated in multiple places that a CSRF attacker can't create custom headers..If the difference is "brute-forcing" the CSRF token, please explain what that would entail, and how the X-CSRFToken header be set?

zerohedge
  • 135
  • 5
  • Step 1 and 3 are contradictory. You clam that the client stores `auth_token` and send it back with every request, then you claim that the client never stores `auth_token`. –  Oct 15 '19 at 09:14
  • @MechMK1 - I've edited my question. `auth_token` is sent with every request because it's a cookie. My second note about the client not storing is that the JS application isn't storing it (obviously it can't because it's an HttpOnly cookie). Is it clear now what's happening? – zerohedge Oct 15 '19 at 09:16
  • In fact, no. I don't know how much you know about how browsers and cookies work, but when a server instructs a client to store a cookie (so that the client can later send that cookie back), the client *by design* stores the cookie. Point 3 is just nonsensical. –  Oct 15 '19 at 09:18
  • 1
    @MechMK1 1. I don't know much, I come to learn from the friendly community of SE. 2. You are referring to the client as the browser, but i've edited the question to indicate that I mean my JS application, the frontend application, right after your first comment. You can call it a typo, I apologize. Does that satisfy you? – zerohedge Oct 15 '19 at 09:20
  • Yes, it's much clearer now what you mean. –  Oct 15 '19 at 09:23
  • I suspect that some of the confusion is because you are conflating the different vulnerabilities XSS (cross site scripting) and CSRF (cross site request forgery)? The CSRF protections "do nothing" to guard against an attacker which has exploited a CSS vulnerability against your users. – Geir Emblemsvag Oct 15 '19 at 10:17
  • @GeirEmblemsvag please explain. I’m defending against XSS by putting the auth token in HttpOnly, and the CSRF cookie + header is for CSRF attacks. What’s wrong with my line of thinking? – zerohedge Oct 15 '19 at 11:39
  • The "httpOnly" flag only prevents that an attacker reads or changes the cookie content using JS. The cookies are still submitted to your API if the attacker makes an XHR call as part of the XSS. Practically speaking, if you have an XSS vulnerability, the attacker can bypass any of your CSRF protections. See for instance https://security.stackexchange.com/questions/121971/will-same-site-cookies-be-sufficent-protection-against-csrf-and-xss – Geir Emblemsvag Oct 15 '19 at 12:49
  • Just so we don't talk cross purposes: I understood your question as asking how to protect the CSRF cookie from an XSS attack; which is sort of a lost cause :) – Geir Emblemsvag Oct 15 '19 at 12:51
  • 1
    @GeirEmblemsvag - No. sorry. That isn’t my question. I shouldn’t have mentioned XSS at all to avoid confusion. My question is at the end of my OP and refers to CSRF, in particular, why in this pattern it needs to be random, etc... – zerohedge Oct 15 '19 at 12:53
  • 1
    @zerohedge Don't worry, the current version of your question is plenty clear. It's just easy to have some miscommunication on forums like this. – Conor Mancone Oct 15 '19 at 13:00

1 Answers1

3

This question is your friend:

CSRF protection with custom headers (and without validating token)

In essence, if you opt to make your X-CSRFToken header something simple like 1, you are falling back simply on the presence of your custom header for CSRF protection. If you have a fixed CSRF token for all users, then an attacker will easily be able to figure this out and will therefore know the CSRF token for all users. Since this will naturally match the cookie you create for all users, an attacker will therefore automatically circumvent the cookie matching requirement of your CSRF system.

Therefore (repeating myself here), your CSRF protection will effectively boil down to the fact that you're checking for the presence of a custom header in the request. This is not a crazy thing to do, because there are currently no known ways for an attacker to set a custom header in a CSRF attack. So for now, this would actually be sufficient protection. In that case though you also might as well not bother with the cookie, since it isn't actually providing additional protection.

Generally though (per the question I linked to above and its answers) checking only for a custom header is discouraged because things change and you never know when someone might find a way to set a custom header on a CSRF attack. If that were to happen, your protection would no longer work and you would be vulnerable to a CSRF attack.

In the end though you have to decide what is the best way to balance the cost (of implementing this security measure) vs the benefit (of securing your application), and decide what security steps work best for you. If your application is an anonymous website for voting on favorite cat pictures, I'd say just stick with the custom-header protection. If you're securing the nuclear launch codes though, I'd go for proper CSRF protection (and a whole lot more!).

Conor Mancone
  • 29,899
  • 13
  • 91
  • 96