在客户端设置XSRF cookie [英] Set the XSRF cookie on the client side

查看:56
本文介绍了在客户端设置XSRF cookie的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想通过设置cookie并在每个POST/PUT/DELETE请求中发送具有相同值的HTTP标头来为我的应用程序实现CSRF预防机制.在我所阅读的所有地方,最佳实践都建议应从服务器设置csrf cookie.我正在使用AngularJS构建单页应用程序,并且他们还建议出于安全原因,服务器应在第一个GET请求中发送cookie.

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.

我的问题是-为什么服务器应该发送cookie,而不仅仅是使用简单的javascript和生成的随机uuid值在客户端上进行设置?

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?

此外,如果您有一个所有人都可以访问的公共应用程序,并且仍然需要保护它不受csrf的干扰,那么服务器端将如何记住它发送给哪些用户的令牌(如果他们没有会话cookie)?

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?

推荐答案

服务器为什么要发送cookie ...

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...

在交流之前进行的任何设置都具有不同的目的,请查看 https://zh-CN.wikipedia.org/wiki/Shared_secret https://en.wikipedia.org/Wiki/Symmetric-key_algorithm .您的应用是公开的,可以回答为什么不提前在客户端上进行设置.

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.

使用简单的javascript和生成的随机uuid值?

using simple javascript and a generated random uuid value?

设置uuid是没有意义的,因为任何人都可以做到:您的服务器无法区分应用程序中的uuid和黑客的uuid.

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.

此外,如果您有一个可以被所有人访问的公共应用程序,但仍然需要保护它免受csrf的侵害...

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

但是,如果您的应用程序(及其中的API)是公开的,则您不应该对其进行保护,对吗?尝试 curl https://api.github.com/users/mongodb/repos .我最近了解到,您可以通过提供cookie atl.xsrf.token = no-check (也可以通过标头使用,请注意JSESSIONID仍用于实际身份验证)来禁用Bamboo api的XSRF保护.

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).

如果服务器端没有会话cookie,服务器端将如何记住它发送给什么用户的令牌?

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

XSRF令牌通常作为自定义的 X- HTTP标头进入.甚至作为路径/查询参数,也不需要Cookie.

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

XSRF仅用于通过使用api随其上次请求提供给您的应用程序的令牌(或初始的 GET 在此免费获得新令牌)来对应用程序的下一个请求进行身份验证.正如另一个答案正确指出的那样,服务器可以决定在每个幂等请求中更改令牌.标准做法是为每个请求都使用一个新令牌,无论如何生成它们都是很便宜的.

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:

  • 如果我设法注入一些JavaScript并到达令牌所在的应用的Cookie(或dom或js名称空间,或通过某些js getter访问您的令牌),那么我可以提出经过身份验证的 Delete 请求到您的api
  • 如果我设法将您的应用重定向到我的服务器(任何形式的欺骗您的DNS,没有SSL等等),并且获得了您的令牌,则在以下情况下,我的下一个 Delete 请求可能会被拒绝:
    • 您的服务器希望每个请求都有一个新令牌,并且...
    • 您在两次之间提出请求的速度都比我快,我会再试一次,或者...
    • 服务器足够聪明,可以看到具有相同令牌的多个请求来自不同的IP,并且至少会给您一个类似gmail的警告
    • 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

      总而言之,请勿将csrf用于您的公共api.在呈现数据时使用它,在代码或幂等调用中包含远程资源,但要加以妥善保护.希望这一切都有道理.

      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.

      这篇关于在客户端设置XSRF cookie的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆