security - 如何在 RESTful 应用程序中防止 CSRF?

标签 security http rest authorization csrf

跨站请求伪造 (CSRF) 通常可以通过以下方法之一来防止:

  • 检查 referer - RESTful 但不可靠
  • 将 token 插入表单并将 token 存储在服务器 session 中 - 不是真正的 RESTful
  • 神秘的一次性 URI - 出于与 token 相同的原因而不是 RESTful
  • 为此请求手动发送密码(不是用于 HTTP 身份验证的缓存密码)- RESTful 但不方便

我的想法是使用用户密码、神秘但静态的表单 ID 和 JavaScript 来生成 token 。

<form method="POST" action="/someresource" id="7099879082361234103">
    <input type="hidden" name="token" value="generateToken(...)">
    ...
</form>
  1. GET/usersecret/john_doe 由 JavaScript 从经过身份验证的用户那里获取。
  2. 响应:OK 89070135420357234586534346 这个 secret 在概念上是静态的,但可以每天/每小时更改......以提高安全性。这是唯一的 secret 。
  3. 使用 JavaScript 读取神秘的(但对所有用户来说都是静态的!)表单 ID,将其与用户密码一起处理:generateToken(7099879082361234103, 89070135420357234586534346)
  4. 将表单连同生成的 token 发送到服务器。
  5. 由于服务器知道用户密码和表单 ID,因此可以在发送之前运行与客户端相同的 generateToken 函数并比较两个结果。只有当两个值相等时,操作才会被授权。

尽管没有 JavaScript 就无法工作,但这种方法有什么问题吗?

附录:

最佳答案

这里有很多答案,也有不少问题。

你不应该做的事情:

  1. 如果您需要从 JavaScript 读取 session token ,那您就大错特错了。您的 session 标识符 cookie 应始终在其上设置 HTTPOnly,以便脚本无法使用它。

    这种保护使得 XSS 的影响大大降低,因为攻击者将无法再获得登录用户 session token ,就所有意图和目的而言,它等同于应用程序中的凭据。你不希望一个错误就给了王国的 key 。

  2. 不应将 session 标识符写入页面内容。这与您设置 HTTPOnly 的原因相同。这意味着您的 csrf token 不能是您的 session ID。它们需要具有不同的值。

你应该做的事情:

  1. 关注OWASP's guidance :

  2. 具体来说,如果这是一个 REST 应用程序,您可以 require double-submission of CSRF tokens .如果这样做,请确保将其定义为特定的完整域 ( www.mydomain.com ) 而不是父域 (example.com),并且您还使用了越来越受欢迎的“samesite”cookie 属性。

只需创建一些随机加密的东西,将其存储在 ASCII 十六进制或 Base64 编码中,并在服务器返回页面时将其作为 cookie 添加到您的表单中。在服务器端确保 cookie 值与表单值匹配。瞧,您已经消除了 CSRF,避免了对用户的额外提示,并且没有让自己面临更多漏洞。

注意:正如@krubo 所述,双重提交技术 has been found to have some weaknesses (See Double-Submission) .由于此弱点要求:

  1. 您定义一个范围为父域的 cookie。
  2. You fail to set HSTS .
  3. 攻击者控制了用户和服务器之间的一些网络位置

我觉得这个弱点更多属于“Cool Defcon Talk”类别,而不是“Realworld Security Risk”。在任何情况下,如果您要使用双重提交,采取一些额外的步骤来完全保护自己也无妨。


新更新 07/06/2020

我最喜欢的双重提交方式是像以前一样在请求正文中创建并传递加密随机字符串;但不是让 cookie 成为完全相同的值,而是让 cookie 成为证书签名的字符串的编码值。这在服务器端仍然很容易验证,但攻击者很难模仿。您仍应使用 samesite Cookie 属性和我之前在帖子中概述的其他保护措施。

关于security - 如何在 RESTful 应用程序中防止 CSRF?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2392100/

相关文章:

c++ - C++ 中的安全内存分配器

android - 制作 Http Get 和 Post 请求

c# - 在 C# .NET 中按资源组列出 azure 工作区

python - 用于 Django 项目/应用程序的 RESTful API

windows-mobile - RESTful Web 服务、.net 紧凑框架和许多 HTTP 方法

azure - 机器人如何发现我的 Azure 子域?

c# - 用户主体安全。禁用不需要的智能卡提示?

security - JSONP 可以安全使用吗?

java - 无法在 Postman 中获取 HTTP 调用的响应

http - 如何将 cookie 添加到 typescript 和 angular2 中的任何 http.get 请求?