我是否需要在此设置中使用由 oauth2 和基本身份验证 SSO 身份验证服务器支持的 REST API 进行 CSRF 保护?

信息安全 csrf oauth2
2021-08-26 11:13:01

我已经看到了如果我什至不使用 cookie 是否可以使用 CSRF 的答案?但是有两个相互矛盾的答案,而且问题本身也没有提供那么多信息。

我正在创建一个 REST API,将由在另一个域上运行的 Web 客户端(我们自己创建)使用,因此我们将执行 CORS 请求。此 API 作为 oauth2 资源服务器运行,因此访问受到身份验证标头中传递的访问令牌的限制。我们那里没有任何 cookie,一切都是无状态的。我正在遵循https://spring.io/blog/2011/11/30/cross-site-request-forgery-and-oauth2文章中的建议

  • 我们将使用 SSL
  • 我们已经预先注册了重定向 uri
  • 根据https://oauth.net/2/grant-types/implicit/上的建议,我们唯一的授权类型是授权代码,不需要客户端机密(因为 Web 客户端源是公开的)而不是隐式授权类型
  • 客户端在进行实际资源服务器调用时使用标头进行身份验证
  • 获取访问令牌是通过在表单参数 ( x-www-form-urlencoded) 中传递 1 次授权码来完成的,这似乎是正常的方式,不应该卡在浏览器历史记录中,因为它不是查询参数。
  • 客户端在获取授权码时也会使用一些秘密状态参数。在这种情况下,我不确定是否有任何意义,因为客户端不依赖秘密通过交换代码来获取访问令牌。
  • 对于您实际获得访问令牌的 oauth/token 端点,唯一允许的来源是我们的 Web 客户端的域
  • 对于 oauth/authorize 端点,不允许使用 CORS。也许这太过分了,因为重定向 uri 无论如何都只会指向我们自己的域?

我认为这几乎涵盖了那方面的所有内容。

现在还有另一种可能的攻击媒介,即 oauth2 身份验证服务器本身,它应该是 SSO 并且确实有会话并且可以通过基本身份验证访问。但是,对于 csrf 攻击,您似乎无法采取任何实际有用的操作。您可以向这些 oauth 端点发出请求,但您必须能够读取结果,这被 CORS 配置和重定向 uri 预先注册的事实所阻止。那里没有 POST 可以更改密码、重置电子邮件地址等,所有这些实际上也暴露为资源服务器。

我错过了什么吗?您将如何在这里探测漏洞?

1个回答

要回答您最初的问题:如果您没有使用 cookie(会话)并且没有在浏览器中使用基本身份验证,则不需要在资源服务器上实施 CSRF 对策。

浏览器会为您访问的每个域名存储 Cookie 和基本授权标头,每次您向站点发送请求时,保存的 Cookie 和基本授权标头都会自动添加到请求标头中。

由于您使用的是访问令牌,并且可能使用 发送它Authorization: Bearer <token>,因此您应该是安全的。您的浏览器不知道如何处理这种授权,这也是您必须在每个请求中手动添加此标头的原因。

重定向 URI

您正在使用 OAuth 2.0 标准推荐的预注册重定向 URI。这可确保您的授权服务器仅授权代码发送到您信任的站点。

重要的是,您的重定向 URI 使用的是安全方案,例如 HTTPS,否则您很容易受到 MITM 攻击。

交换访问令牌的授权码

当您从授权服务器重定向回来时,您的站点正在通过查询参数接收授权代码。最有可能的是,您会立即将授权代码交换为访问令牌,之后应该会撤销授权代码。

state此处应使用该参数来防止 CSRF 攻击,例如通过向authorize端点发送随机值,并检查您是否收到与授权码相同的值。在 SPA 中,您可以将随机值保存在本地存储中,即

在 SPA 中,您不必担心这一点,例如在有状态的服务器端 Web 应用程序中。如果攻击者从他自己的网页将您重定向到授权页面,会发生什么?您最终会进入自己的 SPA,攻击者应该无法继续。

在有状态的服务器端应用程序中,通过执行此授权,您实际上可能会将帐户链接在一起,并且事情可能会开始发生。(当然,取决于应用程序。)

token端点上的 CORS

首先,CORS 仅由您的浏览器检查,因此您不能依赖它来阻止攻击者使用您的token端点。

为了在此处规避 CORS,攻击者所要做的就是创建一个代理端点,该端点仅将请求发送到您的token端点。

此外,token端点只有在收到有效的授权码时才能工作。

authorize端点上的 CORS

通常,您会将用户重定向到authorize端点,他们将在此处(登录并)单击授权按钮,授予对应用程序的访问权限。

如果没有 CORS,一个可能的攻击是攻击者可以创建自己的站点,并在其中使用XHR/fetch来检索您的authorize页面。并且假设用户在您的authorize页面上(有状态地)登录,他将能够在未经用户同意的情况下单击授权按钮。

没有需要使用XHR/fetch来检索authorize页面的场景。因此,您可以使用 CORS 安全地阻止它。

授权服务器

如果您的授权服务器是有状态的,正如您所写,那么您应该在执行可以更改某些内容的操作时实施 CSRF 保护。通常这样做是最佳实践,如果您将来添加更新密码功能,您已经拥有防止 CSRF 的必要代码。

建议

听起来您了解 OAuth 规范。看起来你正在做你应该做的事情。

  • 显而易见的建议是使用带有预加载(和 HPKP)的 HSTS,以防止 MITM 攻击。
  • 确保您的授权代码是短暂的,并且只能使用一次。它们不需要很长时间有效,在正常情况下,它在被授予后立即使用。
  • 不要在数据库中存储最终访问令牌、刷新令牌、授权代码。而是存储一个标识符(例如 64 字节的随机数),并发布一个签名版本(例如 JWT)。这可以防止攻击者从您的数据库中提取访问令牌,因为攻击者无论如何都无法使用它。
  • 使用 OAuth 的标准实现,不要自己动手。