刷新令牌轮换 - 真的足够了吗?

Posted

技术标签:

【中文标题】刷新令牌轮换 - 真的足够了吗?【英文标题】:Refresh Token Rotation - is it really enough? 【发布时间】:2021-02-18 19:26:26 【问题描述】:

在使用 OIDC 服务器进行身份验证的单页应用程序 (javascript) 的上下文中,保持会话活动(在过期后获取更多令牌)的标准和推荐方法是使用 HttpOnly Cookie 并执行静默更新在 iframe 中。太好了,因为浏览器无法保密,所以不涉及刷新令牌。

现在浏览器似乎要阻止跨域 Cookie(Safari 和 Brave 已经这样做了,Chrome 似乎会是下一个),所以如果服务器位于不同的域中,这似乎是未来唯一的方法将使用 Refresh TokensRefresh Token Rotation(可能还有 Reuse Detection),这似乎可以缓解问题。但真的吗?

场景 1) 刷新令牌 (RT1) 被盗,由于轮换,用户请求新令牌并取回新的刷新令牌 (RT2)。 RT1 现在无效,攻击者无法使用。太好了。

场景 2) 刷新令牌 (RT1) 被盗,攻击者执行获取新令牌 (RT2) 的请求,用户使用旧令牌 (RT1)现在一切都被丢弃了,用户必须再次登录(重用检测),攻击者的令牌也无效。伟大的。好吧,我在这里看到了一个问题(用户必须重新登录并且不知道为什么),但至少问题已经解决了。

场景 3) 这是我在任何地方都没有看到的场景。假设攻击者在不使用它们的情况下窃取每个后续​​ RT,因此它继续窃取 RT1。用户刷新,攻击者也窃取了 RT2。一切正常,因为攻击者没有使用令牌,但也许他将所有令牌发送到其他地方进行存储。最后,用户关闭窗口,攻击者提取了 RT1 和 RT2。此时,攻击者可以使用最新的RT(RT2)冒充用户,直到用户返回应用程序。假设他离开一周,攻击者有一周的新访问令牌(他可以不断刷新令牌)。直到最后没有人注意到任何事情。使用 Cookie,攻击者只能在浏览器会话期间进行操作,现在它有更多的时间。

那么...带有重用检测的 RTR 真的足够安全吗?主要论点是“这始终是一个风险/收益选择”,我明白了,但怎么会是 2020 年,我们仍然遇到浏览器问题?你觉得我错过的第 3 个场景有什么问题吗?老实说,会话 cookie 一直是最好的选择,浏览器会阻止我们在这种常见情况下使用它们的事实让我抓狂:)

谢谢。

PS。我将在此处复制一些我找到的有关此问题的资源:

https://pragmaticwebsecurity.com/articles/oauthoidc/refresh-token-protection-implications.html

"RTR 不是一个包罗万象的安全措施。如果攻击者设法在应用关闭之前获得最后一个刷新令牌,他们可能能够继续轮换被盗的刷新令牌。为了避免长期滥用对于被盗的刷新令牌,安全令牌服务可以将该刷新令牌的生命周期链接到用户与安全令牌服务的会话的生命周期。这样做会在会话到期时使刷新令牌失效。"

这是我在场景 3 中提出的观点,但他建议的解决方案是将 RT 链接到用户的会话。所以,我们又在使用会话 Cookie,不是吗?如果我们不能使用它们怎么办?这种情况下的 RT 应该是我们无法使用跨域 cookie 时的替代方案。

https://leastprivilege.com/2020/03/31/spas-are-dead/

这个人似乎同意我的观点,即使使用 RTR 的 RT 也不够安全,SPA 需要连接到同一域上的后端才能像以前一样工作。

【问题讨论】:

【参考方案1】:

这是一个有趣的领域,它通常是可用性、安全性、性能和成本之间的权衡。行业目前的状况非常不理想,但我希望其中的一些内容可以帮助您了解主要问题。

在浏览器中刷新令牌

在使用此解决方案之前,我会确保授权服务器正确支持OAuth 2.1 RTP recommendations - 没有多少授权服务器支持。

然后我会确保我只将刷新令牌存储在应用程序的内存中,因为不建议将令牌存储在本地存储中。这意味着:

多标签浏览或重新加载页面需要通过您提到的基于 iframe 的旧解决方案进行令牌刷新 这不会在 Safari 中静默运行,因此会有一个浏览器重定向,可用性利益相关者可能会抱怨

安全方面

您的 SPA 安全性当然不仅仅是令牌机制。您需要确保安全利益相关者接受该解决方案,并且您需要考虑威胁,例如攻击者可以使用令牌/cookie 做什么。

前端模式的后端

这样做的一个大问题是,您通常需要一个后端,它发出相同的域 HTTP 仅加密 cookie,用 C#、Node、Java 等编码。

这对于 SPA 架构来说可能非常具有侵入性:

通过内容交付网络将 Web 静态内容推送到全球多个位置是不可能的,或者更加困难 您可能需要对来自 SPA 的每个 API 调用进行两次跳跃,这会增加复杂性,尤其是在缓存和 API 错误响应等领域 使用身份验证 cookie 无法“解决”安全问题,许多浏览器威胁仍需要处理

我的资源

您选择的解决方案可能取决于您的目标最终状态。我现在更喜欢的全面架构选项是将访问令牌存储在浏览器内存中,并使用 Same Domain HTTP Only Encrypted Cookie 进行令牌更新。

我的以下帖子可能会帮助您更多地思考您想要从自己的解决方案中得到什么:

SPA End State Browser Threat Model

【讨论】:

谢谢,我会尽快阅读资源 :) 但最终你说的是我的意思:即使使用 RTR 和重用检测,如果你不这样做,这也不会涵盖第三种情况t 使用 ALSO cookie。请记住,无论谁推荐这条路径都是为了避免使用 Cookie,所以我同意你的观点,即“不应该存储 RT”(即使它们也可以从内存中窃取......)但这违背了他们的目的(替代无声更新)。如果用户必须在刷新后再次登录,那有什么好处呢?您的最终解决方案对我来说似乎是正确的:您正在使用 Cookie 来维护会话,而不是 RT :) 是的 - 认为我们同意 - 尽管我会说这是关于可用性、简单性以及安全性。如果我可以将刷新令牌与推荐的 RTP 一起使用,仅将它们存储在内存中,并且没有可用性问题,我会选择该选项。我认为 RT 并不比用户使用 Fiddler 等代理工具轻松访问他们自己的身份验证 cookie 更糟糕。当然,我的 Web UI 还需要良好的 XSS 和内容安全策略保护,以便恶意 Javascript 代码无法访问 RT,就像它无法访问 auth cookie 一样。 是的,但如果操作正确,恶意代码将永远无法访问身份验证 cookie :) 唯一的问题是 CSRF,但我们有相应的工具。如果您使用适当的 Cookie 遇到 XSS 问题(无论如何您都被搞砸了),攻击者只能在受害者的浏览器关闭之前工作,但是如果他窃取 RT,他可以创建无限 AT,就此而言,我认为它更差。正如您所说,访问 Cookie 的唯一方法是使用外部工具:我们无法控制。如果有人进入您用户的设备,我认为这不是开发人员的责任。 另外,我们甚至没有谈论处理这些令牌:轮换、重用检测、撤销、需要更多带宽等......这是可行的,关键是它不是免费的,而且您也必须始终在服务器上维护某种状态。

以上是关于刷新令牌轮换 - 真的足够了吗?的主要内容,如果未能解决你的问题,请参考以下文章

如何基于使用 Oauth2 协议的身份验证改进 JWT 访问令牌和刷新令牌?

SPA 中的令牌存储和刷新选项

在 spotify android sdk 中刷新令牌?

支持 JWT 密钥轮换的承载令牌认证的 Owin 中间件

访问和刷新令牌的生命周期

刷新令牌如何为 jwt 添加安全性?