Set the XSRF cookie on the client side

谁说胖子不能爱 提交于 2021-02-08 08:13:14

问题


I want to implement a CSRF prevention mechanism for my application by setting a cookie and sending an HTTP header with the same value with every POST / PUT / DELETE request. Everywhere I read, the best practices suggest that the csrf cookie should be set from the server. I'm building a single page app using AngularJS and they also suggest that for security reasons the cookie should be send by the server on the first GET request.

My question is - why should the server send the cookie and not just set it on the client using simple javascript and a generated random uuid value?

Also, if you have a public app that can be accessed by everyone and still need to protect it from csrf, how would the server side remember what token it sends to what user, if they do not have session cookies?


回答1:


why should the server send the cookie...

So that the server can know (authenticate) that the second request from your app came exactly from your app (since that same app is the only receiver of the first request's response). I say the token is not used for authorization since its derived directly from the user which the token maps to. For example, you can't use the token to delete another user. However, your code can still get exploited and that token be compromised to malicious code but let's think about it later on.

...and not just set it on the client...

Anything set in advance of communication serves a different purpose, have a look at https://en.wikipedia.org/wiki/Shared_secret or https://en.wikipedia.org/wiki/Symmetric-key_algorithm. Your app is public which answers why not set it on the client in advance.

using simple javascript and a generated random uuid value?

Setting a uuid is pointless because any one can do it: your server can't distinguish between uuid's from your app and hacker's ones.

Also, if you have a public app that can be accessed by everyone and still need to protect it from csrf...

But if your app (and the API therein) is public you shouldn't protect it, right? Try curl https://api.github.com/users/mongodb/repos. I recently learnt you can disable Bamboo api's XSRF protection by supplying cookie atl.xsrf.token=no-check (also works via header, note that JSESSIONID is still used for the actual authentication).

how would the server side remember what token it sends to what user, if they do not have session cookies?

The XSRF token would normally come in as a custom X- HTTP header. Or even as a path/query param, no cookies needed.

XSRF is only used to authenticate your app's next request by using a token that your api gave to your app with its last request (or the initial GET where you get new token for free). As the other answer correctly pointed out, the server can decide to change the token with every idempotent request. Standard practice is to have a new token for every request, they are cheap to generate anyway.

Last but not least, think about some exploit scenarios:

  • If I manage to inject some javascript and get to your app's cookies where the token is (or dom or js namespace or access your token through some js getter), then I can make authenticated DELETE requests to your api
  • If I manage to redirect your app to my server (any kind of spoofing your DNS, no ssl and so on) and I get to your token, my next DELETE request might get rejected if:
    • your server expects a new token with every request and...
    • you managed to be faster than me to make that request in between, I will try again or...
    • the server is smart enough to see that multiple requests with the same token come from different IP's and at least give you a warning like gmail
  • If I manage to redirect your server api's response (meaning I have a fresh token), my DELETE request will succeed but your next request will give you a warning saying you're access a stale resource (which my request has modified somehow). I see that as an optimistic locking over your session.

In summary, don't use csrf for your public api. Use it when you render data, include remote resources in your code or in idempotent calls but then guard it well. Hope it all makes sense.




回答2:


The whole point of having a CSRF token is so that some malicious user or program won't impersonate another user. Traditionally, a CSRF token is generated by the server and stored in the session for that user. This will automatically create a cookie for that user and your back-end code should add a hidden form field for the CSRF token to facilitate the form submission. So whenever a users sends a POST / PUT / DELETE request to your server, you always check if the CRSF token in the server matches with the one submitted by the user.

Also, if you have a public app that can be accessed by everyone and still need to protect it from csrf, how would the server side remember what token it sends to what user, if they do not have session cookies?

Well, the server does not really care if the user is authenticated. For any user that visits your site you should create a CSRF token and add it to any form or anything that creates a non-idempotent request to your site. Adding a CSRF token for a user on the session will just create a cookie and serve it to the browser, this does not require log on. Again, this will make a life of an attacker hard because firstly, they won't have the right cookie to send and second, it's not very like that they will guess the CSRF token that was generated by the user.



来源:https://stackoverflow.com/questions/22080064/set-the-xsrf-cookie-on-the-client-side

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!