Javascript 在客户端设置XSRF cookie

Javascript 在客户端设置XSRF cookie,javascript,angularjs,cookies,csrf,Javascript,Angularjs,Cookies,Csrf,我想为我的应用程序实现一个CSRF预防机制,方法是设置一个cookie,并在每个POST/PUT/DELETE请求中发送一个具有相同值的HTTP头。无论我读到哪里,最佳实践都建议从服务器设置csrf cookie。我正在使用AngularJS构建一个单页应用程序,他们还建议出于安全原因,cookie应该在第一个GET请求时由服务器发送 我的问题是-为什么服务器应该发送cookie,而不只是使用简单的javascript和生成的随机uuid值在客户端上进行设置 此外,如果您有一个人人都可以访问的公

我想为我的应用程序实现一个CSRF预防机制,方法是设置一个cookie,并在每个POST/PUT/DELETE请求中发送一个具有相同值的HTTP头。无论我读到哪里,最佳实践都建议从服务器设置csrf cookie。我正在使用AngularJS构建一个单页应用程序,他们还建议出于安全原因,cookie应该在第一个GET请求时由服务器发送

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


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

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

此外,如果你有一个公共应用程序,每个人都可以访问,并且 仍然需要保护它不受csrf的影响,服务器端会如何记住 如果用户没有会话cookie,它会向用户发送什么令牌

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

为什么服务器要发送cookie

这样服务器就可以知道(验证)来自你的应用的第二个请求完全来自你的应用(因为同一个应用是第一个请求响应的唯一接收者)。我说令牌不用于授权,因为它直接来自令牌映射到的用户。例如,您不能使用令牌删除其他用户。但是,您的代码仍然可能受到攻击,并且该令牌可能会被恶意代码破坏,但让我们稍后再考虑

…而不仅仅是在客户端设置它

在交流之前设置的任何东西都有不同的用途,看一看或看一看。你的应用程序是公共的,它回答了为什么不提前在客户端设置它

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

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

此外,如果你有一个公共应用程序,每个人都可以访问,但仍然需要保护它免受csrf

但是如果你的应用程序(以及其中的API)是公开的,你不应该保护它,对吗?试试卷曲https://api.github.com/users/mongodb/repos。我最近了解到,您可以通过提供cookie
atl.XSRF.token=no check
(同样通过头工作,注意JSESSIONID仍然用于实际身份验证)

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

XSRF令牌通常作为定制的
X-
HTTP头提供。甚至作为路径/查询参数,也不需要cookies

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

最后但并非最不重要的一点是,考虑一些利用漏洞的场景:

  • 如果我设法注入一些javascript并访问应用程序的Cookie(或dom或js命名空间,或通过一些js getter访问您的令牌),那么我可以向您的api发出经过身份验证的
    删除
    请求
  • 如果我设法将您的应用重定向到我的服务器(任何类型的欺骗您的DNS、无ssl等),并访问您的令牌,我的下一个
    删除
    请求可能会被拒绝,如果:
    • 您的服务器希望每个请求都有一个新令牌,并且
    • 你设法比我更快地提出这个请求,在这期间,我会再试一次,或者
    • 服务器足够聪明,可以看到多个具有相同令牌的请求来自不同的IP,至少会给你一个类似gmail的警告
  • 如果我设法重定向服务器api的响应(意味着我有一个新的令牌),我的
    DELETE
    请求将成功,但您的下一个请求将向您发出警告,说明您正在访问过时的资源(我的请求以某种方式修改了该资源)。我认为这是对您的会话的乐观锁定

总之,不要将csrf用于公共api。在呈现数据时使用它,在代码或幂等调用中包含远程资源,但要保护好它。希望这一切都有意义。

“如果用户没有会话cookie,服务器端如何记住它发送给哪个用户的令牌?”——那么首先,它必须有一些其他标准来识别用户,你不这么认为吗?你用什么方式将CSRF令牌从服务器传递到客户端并返回并不重要。