为什么我应该在JWT令牌中放置CSRF令牌?

7

我想对JWT令牌和CSRF提出疑问,这来自于Stormpath的帖子,该帖子解释了在localStorage或cookie中存储JWT的优缺点。

如果您使用JS从cookie中读取值,这意味着您无法在cookie上设置Httponly标志,因此现在您站点上的任何JS都可以读取它,从而使其与将某些内容存储在localStorage中的安全级别完全相同。
我正在尝试理解为什么他们建议将xsrfToken添加到JWT中。将JWT存储在cookie中,然后将其提取出来并将JWT放置在HTTP标头中,并基于HTTP标头对请求进行身份验证,是否能够实现与Angular的X-XSRF-TOKEN相同的效果?由于其他域无法从cookie中提取JWT,因此其他域不能代表用户发出请求。我不理解JWT中xsrfToken的目的 - 也许它只是额外的防御层 - 这意味着攻击者必须在您的站点上有一个受损的脚本并在那时对用户进行CSRF攻击。所以他们必须用两种方式打击您才能实施攻击。
该帖子链接在this answer中,其中说:
最后一步是确保每个HTTP请求都有CSRF保护,以确保外部域发起的请求无法正常工作。然后,在您的服务器的每个请求中,确保您自己的JavaScript代码读取Cookie值并在自定义标头(例如X-CSRF-Token)中设置该值,并验证服务器上的每个请求的该值。外部域客户端无法为向您的域发送的请求设置自定义标头,除非外部客户端通过HTTP Options请求获得授权,因此他们任何尝试CSRF攻击(例如在IFrame等)都将失败。即使他们可以设置自定义标头,他们也无法访问存储JWT令牌的Cookie,因为只有在相同域上运行的JavaScript才能读取Cookie。他们唯一的方式是通过XSS攻击,但如果存在XSS漏洞,则在JWT中包含xsrfToken也会受到威胁,因为在受信任的客户端域中运行的恶意脚本可以访问Cookie中的JWT并在请求中包括一个带有xsrfToken的标头。因此方程式应该是:TLS+ 存储在安全Cookie中的JWT + 请求头中的JWT + 没有XSS漏洞。
如果客户端和服务器在不同的域中运行,服务器应该发送JWT,客户端应该使用JWT创建cookie。我认为这种情况下方程仍然有效。
更新:MvdD同意我的观点

由于浏览器不会自动添加头信息到您的请求中,因此它不易受到CSRF攻击。

2个回答

9
我是Stormpath博客文章的作者。 将XSRF令牌存储在JWT中并不是关于它在JWT中,而是关于它在cookie中。 cookie应该是httpOnly,所以您不能从Javascript中读取它。
现在,我认为引起一些混乱的是我谈论angular的地方。 Angular也设置了它自己的XSRF cookie(它不是httpOnly),以便在请求时将其放入标头中(只能由同一域上的Javascript执行)。 这些不是同一个cookie。
如果您考虑在应用程序中实现XSRF支持,则已通过存储服务器端状态来完成,并且存储XSRF的目的是保持无状态的。 在这里,您将验证JWT签名,从声明中获取XSRF,并将其与标头进行比较。
你的问题的答案就是为了避免在服务器上存储状态。

谢谢你的回答,你写了一篇很好的文章!但我仍然不明白为什么需要XSRF令牌。也许如果你分享一个具体的案例,在非httpOnly cookie中存储JWT并在头部将其发送回服务器(使用TLS和没有XSS漏洞),用户可能会在不知情的情况下发起恶意请求。 - gabrielgiussi
刚刚发布了一个答案,请告诉我您的想法。 - Chiedo
我也是JMU毕业生,同为Tom :) - Chiedo
使用JWT中明确的XSRF的缺点是会增加其大小。为什么不直接使用JWT的哈希作为XSRF令牌呢?毕竟,如果攻击者可以读取仅限https的cookie,您的XSRF令牌并没有添加太多价值。而且,您可以在不需要服务器端状态和额外cookie大小的情况下验证哈希。 - Eamon Nerbonne
@Tom,快点,你认为我们在使用JWT进行身份验证时应该使用xsref cookie并进行验证吗? - Nexus23

9

我的理解是:

  • 存储JWT是一个HTTP-only cookie。
  • 在JWT中存储XSRF令牌的哈希版本。
  • 在用户登录时向客户端发送XSRF令牌,以便他们可以将其存储在本地存储中。
  • 稍后当客户端发送请求时,JWT会自动通过cookie发送,并且您还会通过标头或查询变量发送XSRF令牌,在服务器端重新进行哈希以比较与JWT中的内容相同。

您的JWT受到防止在XSS中被盗窃的保护,并且您受到XSRF的保护。 XSS仍然可以在您的浏览器上执行,但只能在该会话中对浏览器造成损害。 最终,您无法阻止某人编写一个非常详细的脚本,只需在您的浏览器上运行,因此Web开发人员仍需要传统的安全措施来保护免受XSS的攻击。


1
没错!我在这里针对使用此方法的漏洞面积写了一个答案:https://dev59.com/qpfga4cB1Zd3GeqPDPA4#37817530 - Tom Abbott
另外,去吧公爵! :) - Tom Abbott
2
我仍然对此感到困惑。那么,这是一种安全的技术还是不安全的技术呢?此外,我不明白为什么需要csrf。因为如果我将其存储在本地存储中,则可见。您能否指出一个示例方向! - Gacci
那么为什么不将jwt存储在本地存储中,将XSRF令牌存储在HttpOnly Cookie中呢?这样,只有在服务器同时接收到两者时,jwt的有效性才会得到确认。 - Reiner
1
@Gacci,你只需要调查一下什么是XSRF攻击和CSS攻击 - localStorage可以防止前者(这是一种无法查看localStorage的攻击),而http-only cookie可以防止后者(这是一种无法利用该cookie的攻击)。 - Rob Grant

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接