在有效负载和签名之间拆分 JWT

信息安全 xss csrf jwt 单页应用
2021-08-22 03:53:27

背景:我正在研究单页应用程序上 JWT 令牌的存储解决方案。

  1. 将 JWT 存储在本地存储中是不安全的,并且容易受到 XSS 攻击。
  2. 将 JWT 存储在安全/仅 HTTP cookie 中更安全,但容易受到 CSRF 攻击。

我正在研究以下场景:

身份验证后,刷新令牌存储在仅限 http 的安全 cookie 中。它只能用于获取访问令牌。

授权后,后端会使用 JWT 访问令牌进行响应。JWT 的标头和有效负载部分位于响应正文中。令牌签名不发送,并设置在仅 http 的安全 cookie 中(如果可能,相同站点严格,但我们假设不是这种情况)。标头 + 有效负载存储在内存中。

JWT 包含以下声明

  • iat, nbf, exp(可猜测的 IMO)
  • 与用户身份和权限相关的声明(如果用户身份已知,则可以猜测)
  • jti,包含一个密码安全的随机数(在我的例子中是用 python secrets生成的

发出请求时,标头 + 有效负载由 SPA 在 Authorization 标头中通过 XHR/fetch 发送。签名与 cookie 一起发送。后端连接两者并验证签名。

  1. 这种机制对 CSRF 攻击安全吗?jti 声明是否使授权令牌 + 签名 cookie 成为有效的 CSRF 缓解技术?
  2. 这种机制对 XSS 攻击确实比将 JWT 存储在本地存储中更安全吗?(使用 XSS 的攻击是否也很容易窃取签名,例如使用TRACE 漏洞)。

注意:我读过这个类似的问题,但过于宽泛,所以我发布这个以获得更准确的答案。

1个回答

这种机制对 CSRF 攻击安全吗?

与将整个 JWT 存储在本地或会话存储中相比,这种拆分 JWT 并将签名存储在 cookie 中以及将令牌的其余部分存储在浏览器存储中的方法并没有提供任何额外的针对 CSRF 攻击的保护。是的,它会减轻 CSRF 攻击,但您不需要在服务器上添加拆分和连接 JWT 的不必要开销。将 JWT 存储在本地存储中并仅在授权标头中接受它们足以保护您的应用程序免受 CSRF 攻击。

这种机制对 XSS 攻击确实比将 JWT 存储在本地存储中更安全吗?(使用 XSS 的攻击是否也很容易窃取签名,例如使用 TRACE 漏洞)

如果您只关注能够窃取 JWT 的攻击者,那么这种方法是安全的,除非正如您正确提到的,在服务器上启用了 TRACE。

但是,这并不能使您的应用程序更安全地免受 XSS 攻击。例如,如果我能够在您的应用程序上执行任意 Javascript,我可以从本地存储中获取 JWT 标头+有效负载,然后只需将 XHR 发送到保持 withCredentials 设置为 True 的敏感端点。例如,此端点可能被设计为更改了帐户电子邮件地址。这直接导致帐户接管。无需窃取 cookie 或 JWT。

总结: 这种方法通过将签名与令牌的其余部分分开,确实提供了一些针对会话令牌的保护。然而,当涉及到 XSS 时,窃取会话令牌并不是您应该关注的唯一风险。