使用 JWT 进行身份验证

信息安全 xss 饼干 csrf jwt 本地存储
2021-09-04 13:20:47

我正在构建 SPA (React/Redux) 并需要用户身份验证。我发现了类似的讨论,但没有找到我在下面概述的问题的答案。以下是我发现要实施的一些选项:


选项 1:将 JWT 保存在 localStorage 中

CSRF 攻击:不易受攻击,因为不使用 cookie。

XSS 攻击:易受攻击。前端的任何 JS 代码都可以窃取令牌并将其发送给攻击者。启用 Content-Security-Policy 后,被攻击者无法窃取/发送给自己的 jwt,但仍可以直接从客户端浏览器发出请求。


选项 2:将 JWT 保存在 cookie 中(securehttp-only

CSRF 攻击:易受攻击。客户端可以跟踪恶意网站,这将进行偷偷摸摸的请求,附加cookie,请求成功。

XSS 攻击:易受攻击。Cookie 无法被 JS 读取,但通过 JS 攻击者只需向有效后端发出请求,cookie 就会自动附加,所有请求都会成功。


选项 3:将 JWT(设置了 xsrf_token)保存在 cookie 中 + 将 xsrf_token 保存在 localStorage/JS 可读 cookie 中

解决方案基于,类似于Double Submit Cookies Method

CSRF 攻击:不易受攻击。如果客户端跟踪恶意网站,发出偷偷摸摸的请求,该请求将被丢弃,因为 xsrf_token 没有从客户端的浏览器与 cookie 一起传递。而且,由于 cookie 对攻击者不可见(直接来自客户端浏览器),他无法制作伪造的 xsrf_token 来附加请求。

XSS 攻击:易受攻击。localStorage/JS 可读 cookie 中的 xsrf_token 可以被攻击者 JS 读取。因此,攻击者将能够直接从客户端浏览器注入的 JS 发出恶意请求。


本来想用选项1,但是一直关注XSS,于是开始寻找替代方案。这篇文章和其他一些人建议不要使用 localStorage,并建议使用 Cookie + CSRF 保护。

从收集的数据来看,选项 3 似乎是流行的解决方案,但仍然像选项 1 一样具有 XSS - 注入的 JS 可以直接从客户端浏览器发出恶意请求。唯一的好处是,在选项 1 中,JWT 编码数据可由用户/攻击者读取,而在选项 3 中则不是(存储在 cookie 中)。相关问题

Q1。选项 3 与选项 1 相比还有其他好处吗?

Q2。如果我选择选项 3,我是否会引入一些我尚未考虑的其他攻击媒介?

Q3。是否有任何其他缓解 CSRF 的方法,而不是在前端(localStorage/sessionStorage/Redux 存储/JS 可读 cookie)中保持状态,这总是易受 XSS 攻击?

我知道安全领域没有一颗灵丹妙药。但也许还有其他一些方法/选项来解决这个问题?要删除 XSS,您需要进入完整的 cookie 模式。但如果只使用 cookie,则无论如何都需要在用户前端(localStorage/sessionStorage/Redux 存储/JS 可读 cookie)中有 xsrf_token,这很容易受到 XSS 攻击。这似乎是 catch-22 问题。

1个回答

让我们从简单的部分开始:选项#2 是非选项。它没有 CSRF 保护,因此它本质上是易受攻击的。实际上,选项 #3 几乎是选项 #2,顶部有 CSRF 保护。因此,您将问题集中在#1和#3之间的选择上是正确的。

选项 3 与选项 1 相比还有其他好处吗?

并不真地。而且我不确定你提到的好处——能够用 Http-Only 标志保护 JWT——是一个很大的好处。

能够窃取 JWT 对攻击者来说很方便,因为她可以在自己的计算机上做任何她想做的事情。但考虑到 XSS 漏洞,她可以在自己的计算机上使用 JWT 做的任何事情,她也可以使用注入脚本在受害者计算机上做任何事情。这对攻击者来说可能有点烦人,但它不会阻止一个坚定的对手。

所以最后,我认为#1和#3之间的选择主要是个人喜好之一。我个人更喜欢#1,因为我发现它更干净、更直接。另外,它以一种简洁的方式处理 CSRF 情况,而无需我费力。

如果我选择选项 3,我是否会引入一些我尚未考虑的其他攻击媒介?

或许。

通常,双重提交 cookie 模式的一个弱点是它允许子域攻击使用 JWT 在一定程度上缓解了这种情况。由于已签名,兄弟域无法重写该 cookie。但是(至少在某些浏览器中)子域可以读取它并因此执行 CSRF 攻击。使用 HTTP 标头而不是表单字段进行双重提交会使这种攻击更加困难,如果不是不可能的话(除非是 Flash 漏洞利用)。

请注意,此选项的安全性完全取决于您获得正确的 CSRF 保护。

是否有任何其他缓解 CSRF 的方法,而不是在前端(localStorage/sessionStorage/Redux 存储/JS 可读 cookie)中保持状态,这总是易受 XSS 攻击?

不会。如果您容易受到 XSS 的攻击,那么所有 CSRF 保护都会失效。这并不重要。因为如果我可以做 XSS,我就不再需要 CSRF。因此,在 XSS 的情况下试图想出一种保护 CSRF 的方法不仅是不可能的,而且也是毫无意义的。

你花在思考如何在 XSS 攻击的情况下保护你的 CSRF 令牌的每一分钟都是你应该花一分钟来尝试阻止 XSS 攻击。