【发布时间】:2016-04-19 08:38:42
【问题描述】:
- 在 HTTP 标头中使用
X-CSRF-Token或 token 有什么区别 在隐藏的领域? - 何时使用隐藏字段,何时使用标题,为什么?
我认为X-CSRF-Token 是我使用 JavaScript / AJAX 但我不确定的时候。
【问题讨论】:
标签: security http-headers csrf csrf-token
X-CSRF-Token 或 token 有什么区别
在隐藏的领域?我认为X-CSRF-Token 是我使用 JavaScript / AJAX 但我不确定的时候。
【问题讨论】:
标签: security http-headers csrf csrf-token
CSRF 保护有多种方法。
传统方式(the "Synchronizer token" pattern)通常涉及为每个请求设置唯一的有效 Token 值,然后在随后发送请求时验证该唯一值。通常通过设置隐藏表单字段来完成。令牌值通常是短暂的并且与该会话相关联,因此如果黑客试图重用他们之前在页面上看到的值,或者试图猜测值,他们很可能会失败。因此,只有来自您的应用程序的请求才会起作用,而来自您的应用程序/域外部的伪造请求(也称为跨站点请求伪造)将失败。
这样做的缺点是它要求您的应用程序在所有 HTML 表单上设置此隐藏标记。这些页面现在必须由应用程序动态生成,而以前它们可能是静态 HTML。它还可以破坏后退按钮(因为您需要刷新表单以重新生成另一个唯一的 CSRF 值)。您现在还需要跟踪服务器端的有效令牌并检查任何使用有效令牌的请求。这可能需要付出相当多的额外努力来实施和保持前进。
另一种方法(称为 the "Cookie-to-header token" pattern)是为每个会话设置一次 Cookie,然后让 JavaScript 读取该 cookie 并设置自定义 HTTP 标头(通常称为 X-CSRF-TOKEN 或 X-XSRF-TOKEN 或只是 XSRF-TOKEN)那个值。任何请求都将发送标头(由 Javascript 设置)和 cookie(由浏览器设置为标准 HTTP 标头),然后服务器可以检查 X-CSRF-TOKEN 标头中的值是否与 cookie 标头中的值匹配。想法是只有在同一域上运行的 JavaScript 才能访问 cookie,因此来自另一个域的 JavaScript 无法将此标头设置为正确的值(假设该页面不易受到 XSS 的攻击,从而可以访问此 cookie) .即使是虚假链接(例如在网络钓鱼电子邮件中)也不起作用,因为即使它们似乎来自正确的域,也只会设置 cookie 而不会设置 X-CSRF-TOKEN 标头。
这可能比同步器令牌模式更容易实现,因为您不需要为每个表单的每次调用设置令牌,并且检查也相对简单(只需检查 cookie 与标头匹配)而不是跟踪 CSRF 令牌的有效性。您只需为每个会话设置一个随机值的 cookie。一些前端框架甚至会在看到 cookie 时自动为您生成标头(例如,AngularJS does this)。
缺点是它需要 JavaScript 才能工作(但如果您的应用基本上在没有 JavaScript 的情况下无法工作,这可能不是问题)而且它仅适用于 JavaScript 发出的请求(例如 XHR 请求) - 常规HTML 表单请求不会设置标题。对此的一种变体("Double Submit Cookie" pattern)将X-CSRF-TOKEN 值放在隐藏的表单字段中,而不是放在 HTTP 标头中以解决此问题,但仍保持服务器端逻辑比传统的同步器令牌模式更简单。不过需要注意的是OWASP states some weaknesses with the Double Submit method,当攻击者能够设置 cookie(这通常比读取 cookie 更容易)时,因此建议在这种情况下验证 CSRF 令牌。
此外,同步器令牌模式可以允许额外的控制来强制执行流程(例如,隐藏字段 CSRF 令牌只会在应用程序认为您已发送有效请求以获取该表单时设置)。
哦,一些安全扫描会发现 cookie 没有设置 HTTP-Only 标志,因此可以被 JavaScript 读取 - 但这是故意的,因为它需要能够读取!虚假警报。您可能会认为,只要您使用像 X-CSRF-TOKEN 这样的通用名称,他们就会知道不标记这个,但经常看到它被标记。
【讨论】:
所有这些都用于跨站点请求伪造保护,在向后端发送请求时,您只需使用其中一个。不同的名称来自不同的框架。
这一切都是关于向后端发送csrf value。然后后端会将其与该特定用户存储在数据库中的 csrf 值进行比较。
<input name="my_csrf_input" value="a_hashed_string(the csrf value)"
csrf value放在<meta>标签中,然后在前端我们可以从<meta>标签中获取值并将其发送到后端。特定于 Laravel:
csrf value 进行比较(Laravel 有一个中间件)。XSRF-TOKEN cookie 中获取此标头的值并将其放入每个请求标头中。XSRF-TOKEN的cookie,然后我们使用Angular或Axios的前端框架会自动使用它。特定于 Laravel:
X-CSRF-Token 相比,它是一个更大的字符串,因为 cookie 在 Laravel 中是加密的。【讨论】:
x-xsrf-token 的值并随每个请求一起发送