这对使用 OAuth 令牌保护 cookie 有用吗?

信息安全 验证 Web应用程序 饼干 oauth
2021-08-18 02:39:25

我目前正在尝试设置 OAuth 2.0 身份验证方案来保护一些无状态的 REST Web 服务。这些服务处理敏感信息,并且需要 OAuth 支持。


问题是客户端应用程序 100% 在客户端(Angular/Javascript),并且根本没有用户会话,所以我正在努力解决如何在客户端处理令牌而不将其暴露给攻击者。



计划是做类似的事情:

  1. 使用用户/密码授权从 IdentityServer 获取令牌(客户端应用程序是我们的,并且没有留下任何 client_secret)
  2. 将令牌存储在 cookie 中
  3. 发出请求时,从 cookie 中获取令牌并使用它来签署请求
  4. 当令牌过期时,使用 refresh_token 获取一个新的


要发送请求,我想我可以:

  • 发送 HttpOnly cookie 作为身份验证,而不是签署令牌
  • 使用 Angular 的 XSRF-TOKEN cookie,这意味着该 cookie 应该只能被我们域中运行的 Javascript 访问(尽管我相信这仍然让它容易受到 XSS 攻击?)


cookie 将全部设置为安全,并通过 HTTPS 发送。但是,这似乎仍然不安全,因为令牌仍以明文形式存储。refresh_token 也将在 cookie 中。(我也考虑过本地存储,但除非我错过了什么,否则它似乎并不安全......)



有没有更安全的方法在客户端存储 oauth 令牌?
或者这是可接受的安全性?我在这里想念什么?



参考

Angular XSRF 保护: https : //docs.angularjs.org/api/ng/service/ $http#cross-site-request-forgery-xsrf-protection

1个回答

你不用担心正确的事情

保护位于客户端的信息?

一旦信息到达您的客户端(例如:您的浏览器),您无需执行任何操作来保护它。您可以将访问令牌存储在 cookie 中、网页上的隐藏字段中、html5 本地缓存中或直接在页面中间清晰可见,并且它不会改变任何东西(除了肩部冲浪......)。

一旦访问令牌在客户端上,就担心访问令牌就像打开记事本写下您的电子邮件密码,然后担心攻击者可能会从远程位置窃取该信息。它不会发生。除非您的计算机已经受到威胁,但此时您已经迷路了。

担心在哪里有意义?

通常,您的信息在传输过程中很容易受到攻击。在 OAuth2(隐式流)的情况下,访问令牌将在两个地方传输:

  • 从授权服务器到您的浏览器
  • 从浏览器到资源服务器

在传输过程中保护信息就像在任何地方使用 TLS 一样简单。由于您使用的是 OAuth2 并且它是协议要求的,因此您应该已经这样做了。

现在真正的问题

您打算使用 OAuth2 的方式很可能不是您应该使用的方式。

要了解您可能会滥用 OAuth2 的原因,您必须了解流程。OAuth2定义4个授权流程

  • 授权码(只有一个好但是......继续阅读)
  • 隐式(错误的安全感)
  • 资源所有者密码凭证(可怕的想法)
  • 客户凭证(不适用于您的案例)

由于您使用的是 javascript 客户端,因此唯一适合您的流程是隐式流程,现在开始问题。

隐式流问题

有很多,但让我们只谈谈最关键的一个。访问令牌未绑定到特定客户端!从规范部分 10.16 :

对于使用隐式流的公共客户端,本规范没有为客户端提供任何方法来确定向哪个客户端颁发访问令牌。

这为攻击者冒充您(资源所有者)打开了大门,然后获得对资源服务器的访问权限。让我们继续阅读第 10.16 节:

资源所有者可以通过向攻击者的恶意客户端授予访问令牌来自愿委托对资源的访问。这可能是由于网络钓鱼或其他一些借口。攻击者也可能通过其他机制窃取令牌。然后,攻击者可能会尝试通过向合法的公共客户端提供访问令牌来冒充资源所有者。

在隐式流程(response_type=token)中,攻击者可以轻松地切换来自授权服务器的响应中的令牌,将真实的访问令牌替换为之前发布给攻击者的令牌。

服务器与依赖在反向通道中传递访问令牌来识别客户端用户的本地应用程序通信的服务器可能同样受到攻击者的攻击,该攻击者创建了一个可以注入任意被盗访问令牌的受感染应用程序。

任何假设只有资源所有者才能向其提供资源的有效访问令牌的公共客户端都容易受到此类攻击。

第一次攻击实际上甚至不是攻击,而只是隐式流程中的一个“缺陷”......

下一次攻击

现在开始大麻烦了。您似乎正在尝试使用 OAuth2 隐式流作为委托最终用户身份验证的一种形式,它并不打算提供。返回规范部分 10.16

向客户端验证资源所有者超出了本规范的范围。任何使用授权过程作为委托给客户端的最终用户身份验证形式的规范(例如,第三方登录服务)不得在没有额外的安全机制的情况下使用隐式流程,这些安全机制将使客户端能够确定访问权限颁发令牌供其使用(例如,限制访问令牌的观众)。

在这一点上,你的游戏基本上已经结束了。

如何发动这种攻击?

这很简单。假设您的 REST 服务需要来自 facebook 的访问令牌。攻击者需要做的就是托管一个服务,例如 stackoverflow,并需要来自 facebook 的访问令牌。当您将 facebook 访问令牌提供给 stackoverflow 时,stackoverflow(我们的攻击者)现在可以使用您的 REST 服务冒充您。

所有这一切都是因为访问令牌未绑定到特定客户端。

一个解法

不要使用隐式流,而是使用授权码流。这意味着您的 100% 客户端应用程序将不再是 100% 客户端应用程序。

为什么不使用为用户提供 angularjs 客户端的服务器来处理 OAuth2 流?

参考:https ://www.rfc-editor.org/rfc/rfc6749