2014-02-27 58 views
1

我想为我的应用程序实现一个CSRF阻止机制,方法是设置一个cookie并发送每个POST/PUT/DELETE请求具有相同值的HTTP头。在我阅读的各处,最佳实践表明,应该从服务器设置csrf cookie。我使用AngularJS构建单页面应用程序,他们还建议出于安全考虑,cookie应该由服务器在第一个GET请求上发送。在客户端设置XSRF cookie

我的问题是 - 为什么服务器应该发送cookie,而不是只使用简单的javascript和生成的随机uuid值在客户端上设置它?另外,如果你有一个公共应用程序可以被所有人访问,并且仍然需要从csrf中保护它,服务器端如何记住它向哪个用户发送了什么标记,如果他们没有会话cookie?

+0

_“如果服务器端会记住它向哪个用户发送什么令牌(如果他们没有会话cookie的话)?” - - 它首先必须有其他一些标准来识别用户,你觉得呢? – CBroe

+0

以什么方式将CSRF令牌从服务器传递到客户端并返回并不重要。 – CBroe

回答

0

拥有CSRF令牌的重点在于让一些恶意用户或程序不会模仿其他用户。传统上,CSRF令牌由服务器生成并存储在该用户的会话中。这将自动为该用户创建一个cookie,并且您的后端代码应该为CSRF令牌添加隐藏的表单字段以便于表单提交。因此,无论何时用户向您的服务器发送POST/PUT/DELETE请求,您都会检查服务器中的CRSF令牌是否与用户提交的令牌相匹配。

另外,如果你有一个可以由大家 访问和公共应用程序仍然需要保护它免受CSRF,如何将服务器端记得 什么记号发送给哪些用户,如果他们没有会话cookie?

那么,服务器并不在乎用户是否通过身份验证。对于任何访问您的网站的用户,您应该应该创建一个CSRF令牌并将其添加到任何形式或任何创建一个非幂等请求到您的网站。在会话中为用户添加CSRF令牌只会创建一个cookie并将其提供给浏览器,这不需要登录。同样,这将使攻击者的生活变得艰难,因为首先,他们没有正确的cookie发送,其次,他们不会猜测用户生成的CSRF令牌。

2

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

,使服务器能够知道(验证),从你的应用程序中的第二个请求从您的应用程序来精确地(因为相同的应用程序是只有第一个请求的响应的接收者)。我说该令牌不用于授权,因为它直接从令牌映射到的用户派生。例如,您不能使用该令牌来删除其他用户。但是,您的代码仍然可以被利用,并且该令牌会受到恶意代码的危害,但我们稍后再考虑。

...而不是仅仅将其设置在客户端上...

任何事先沟通的设置用于不同的用途,看看https://en.wikipedia.org/wiki/Shared_secrethttps://en.wikipedia.org/wiki/Symmetric-key_algorithm。您的应用程序是公开的,它解释了为什么不提前将其设置在客户端上。

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

设置uuid是毫无意义的,因为任何人都可以这样做:您的服务器无法区分uuid与应用程序和黑客的区别。

另外,如果你有一个公共的应用程序,每个人都可以访问,还是需要保护它免受CSRF ...

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

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

XSRF令牌通常会作为自定义X- HTTP标头进来。甚至作为路径/查询参数,不需要cookie。

XSRF仅用于通过使用您的API向其应用发送最后一个请求(或免费获得新标记的初始GET)的令牌来验证您的应用的下一个请求。正如其他答案正确指出的那样,服务器可以决定使用每个幂等请求来更改标记。标准做法是对每个请求都有一个新的标记,但它们很便宜。

最后但并非最不重要的,想想一些利用情况:

  • 如果我管理注入一些JavaScript,并获得您的应用程序的饼干,其中令牌(或DOM或JS命名空间或通过一些访问令牌js getter),然后我可以验证DELETE对您的api的请求
  • 如果我设法将您的应用程序重定向到我的服务器(任何欺骗您的DNS,没有SSL等),我得到您的令牌,我的下一个DELETE请求可能会被拒绝,如果:
    • 您的服务器要求每个请求一个新的令牌,并...
    • 你设法比我更快地使之间的要求,我会再试一次或...
    • 服务器是足够聪明地看到,用同样的多个请求来自不同IP的,并至少给你喜欢的Gmail
  • 警告如果我管理重定向服务器API的响应(意思是我有一个新的令牌),我DELETE请求将会成功,但你下一个请求会给你一个警告,说你正在访问一个陈旧的资源(我的请求已被修改)。我认为这是对会议的乐观锁定。

总之,不要为您的公共API使用csrf。在渲染数据时使用它,在你的代码或幂等通话中包含远程资源,但保持良好。希望这一切都有道理。