使用客户端凭据和 OWIN 中间件 OAuth 时的漏洞
Vulnerabilities when using client credentials and OWIN Middleware OAuth
我已经在我们的 MVC 应用程序中实现了 OAuth2 client_credentials 流程。我们的 MVC 应用程序实际上是这种情况下的资源。我很难为这个特定的用例获取样本,因为这个流程主要用于 API 访问,但我还是做到了。
我想与您分享一些实施细节,以询问有关我可能不知道的漏洞的任何信息。我绝不是安全专家,这就是让我来到这里的原因。
在 .NET Framework 4.5.2 中,我使用了 Microsoft.Owin 库 v3.0.1。我知道有更新的方法来设置这类东西(例如 .NET Core 和 IdentityServer4),但正如我所说,我很难为这个特定的用例找到一个可行的示例,所以我尽我所能。
我实现了一个提供者:
public class ApplicationOAuthProvider : OAuthAuthorizationServerProvider
{
private ClientService clientService;
public ApplicationOAuthProvider()
{
this.clientService = new ClientService();
}
public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
string clientId;
string clientSecret;
context.TryGetFormCredentials(out clientId, out clientSecret);
if (clientId == "XXXX" && clientSecret == "XXXXX")
{
context.Validated(clientId);
}
return base.ValidateClientAuthentication(context);
}
public override Task GrantClientCredentials(OAuthGrantClientCredentialsContext context)
{
var client = clientService.GetClient(context.ClientId);
var oAuthIdentity = new ClaimsIdentity(context.Options.AuthenticationType);
oAuthIdentity.AddClaim(new Claim(ClaimTypes.Name, client.ClientName));
var ticket = new AuthenticationTicket(oAuthIdentity, new AuthenticationProperties());
context.Validated(ticket);
//context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });
return base.GrantClientCredentials(context);
}
使用以下启动代码:
public partial class Startup
{
public static OAuthAuthorizationServerOptions OAuthOptions { get; private set; }
static Startup()
{
OAuthOptions = new OAuthAuthorizationServerOptions
{
TokenEndpointPath = new PathString("/Token"),
Provider = new ApplicationOAuthProvider(),
AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(60),
//AllowInsecureHttp = true,
AuthenticationMode = AuthenticationMode.Active,
};
}
public void ConfigureAuth(IAppBuilder app)
{
app.UseCors(CorsOptions.AllowAll)
.UseOAuthBearerTokens(OAuthOptions);
//app.UseOAuthBearerTokens(OAuthOptions);
}
}
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
ConfigureAuth(app);
}
}
然后创建了一个也是网站的客户端应用程序,并最终获得了对资源(MVC 应用程序)的访问权限。资源没有用户,因此没有登录屏幕。资源(现在)有一个令牌端点。客户端应用程序使用其凭据向令牌端点发出请求,然后(在经过身份验证后)在对资源的后续请求中使用该令牌。
我发现了 2 种使用此令牌获取访问权限的不同方式。
- 在请求中包含访问令牌 header。或者
- 将访问令牌作为表单参数包含在内
我的问题是关于这种情况的漏洞:
假设客户端应用程序和服务器之间的所有通信都通过安全通道 (https) 进行,并且客户端应用程序能够以安全的方式维护凭据,那么获取或拦截访问令牌的可能性有多大?或者,此流程(或可能是另一个 OAuth 流程)中是否包含也包含客户端验证的方法?我意识到客户端已经通过 client_id/client_secret 进行了身份验证,但是当我询问验证时,我询问的是请求的来源(当然假设验证方法不包括检查可以被恶意用户欺骗)。
是否有额外的验证步骤我应该包括我可能错过的东西 - 因为那里有很多信息而且我尽力搜索,但我不能声称我对我所拥有的一切都有深刻的理解到目前为止阅读。
如果我错过了一个额外的验证步骤,它如何适应这个 (client_credentials) 流程?
谢谢,
嘉莉
I've found 2 different ways of using this token to gain access.
- Include the access token in the request header. OR
- Include the access token as a form parameter
这意味着您的访问令牌是 Bearer 令牌类型(因此,您还可以使用第三种方式发送访问令牌:使用带有查询参数的 GET 方法)。
what are the chances that an access token could be obtained or intercepted?
Or, are there methods included in this flow (or perhaps another OAuth flow)
that also include client verification?
您有 Bearer 令牌,因此适用 RFC-6750。 威胁缓解 部分回答了您的问题:
首先,您的访问令牌可能会被泄露如果您的客户端应用程序和授权服务器(获取令牌)之间的 TLS 版本,以及之间客户端应用程序和资源服务器(给令牌),存在安全漏洞(摘录:这需要客户端和授权服务器之间的通信交互,以及客户端和授权服务器之间的交互资源服务器,利用机密性和完整性保护。由于 TLS 是强制实施和使用本规范的,因此它是防止令牌通过通信通道泄露的首选方法。)
其次,另一种公开访问令牌的方式是使用 TLS 加速器。如 RFC 的同一部分所述:在某些部署中,包括那些使用负载平衡器的部署,到资源服务器的 TLS 连接在提供资源的实际服务器之前终止。这可能会使令牌在 TLS 连接终止的前端服务器和提供资源的后端服务器之间不受保护。
还有其他方法可以公开访问令牌。
解决方案不是实施另一个 OAuth 流程,而是应用 RFC 第 5.3 节中的建议。作为总结,主要的建议是:
- 始终使用 TLS,
- 验证 TLS 证书链,
- 除了使用 TLS 保护外,还使用令牌加密:例如,使用客户端应用程序和资源服务器之间的共享密钥加密令牌,
- 不要在 cookie 中存储不记名令牌,
- 发行短期不记名令牌,
- 发行范围不记名令牌(使用观众限制)。
这不在 RFC 中,但我会添加此建议:使用相互身份验证。这意味着客户端应用程序必须具有 X.509 证书,该证书必须由资源服务器。这在您选择的特定 Oauth2 流程中是可能的,因为客户端应用程序为资源服务器所知(对于某些替代流程,无法完成)。
我已经在我们的 MVC 应用程序中实现了 OAuth2 client_credentials 流程。我们的 MVC 应用程序实际上是这种情况下的资源。我很难为这个特定的用例获取样本,因为这个流程主要用于 API 访问,但我还是做到了。
我想与您分享一些实施细节,以询问有关我可能不知道的漏洞的任何信息。我绝不是安全专家,这就是让我来到这里的原因。
在 .NET Framework 4.5.2 中,我使用了 Microsoft.Owin 库 v3.0.1。我知道有更新的方法来设置这类东西(例如 .NET Core 和 IdentityServer4),但正如我所说,我很难为这个特定的用例找到一个可行的示例,所以我尽我所能。
我实现了一个提供者:
public class ApplicationOAuthProvider : OAuthAuthorizationServerProvider
{
private ClientService clientService;
public ApplicationOAuthProvider()
{
this.clientService = new ClientService();
}
public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
string clientId;
string clientSecret;
context.TryGetFormCredentials(out clientId, out clientSecret);
if (clientId == "XXXX" && clientSecret == "XXXXX")
{
context.Validated(clientId);
}
return base.ValidateClientAuthentication(context);
}
public override Task GrantClientCredentials(OAuthGrantClientCredentialsContext context)
{
var client = clientService.GetClient(context.ClientId);
var oAuthIdentity = new ClaimsIdentity(context.Options.AuthenticationType);
oAuthIdentity.AddClaim(new Claim(ClaimTypes.Name, client.ClientName));
var ticket = new AuthenticationTicket(oAuthIdentity, new AuthenticationProperties());
context.Validated(ticket);
//context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });
return base.GrantClientCredentials(context);
}
使用以下启动代码:
public partial class Startup
{
public static OAuthAuthorizationServerOptions OAuthOptions { get; private set; }
static Startup()
{
OAuthOptions = new OAuthAuthorizationServerOptions
{
TokenEndpointPath = new PathString("/Token"),
Provider = new ApplicationOAuthProvider(),
AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(60),
//AllowInsecureHttp = true,
AuthenticationMode = AuthenticationMode.Active,
};
}
public void ConfigureAuth(IAppBuilder app)
{
app.UseCors(CorsOptions.AllowAll)
.UseOAuthBearerTokens(OAuthOptions);
//app.UseOAuthBearerTokens(OAuthOptions);
}
}
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
ConfigureAuth(app);
}
}
然后创建了一个也是网站的客户端应用程序,并最终获得了对资源(MVC 应用程序)的访问权限。资源没有用户,因此没有登录屏幕。资源(现在)有一个令牌端点。客户端应用程序使用其凭据向令牌端点发出请求,然后(在经过身份验证后)在对资源的后续请求中使用该令牌。
我发现了 2 种使用此令牌获取访问权限的不同方式。
- 在请求中包含访问令牌 header。或者
- 将访问令牌作为表单参数包含在内
我的问题是关于这种情况的漏洞:
假设客户端应用程序和服务器之间的所有通信都通过安全通道 (https) 进行,并且客户端应用程序能够以安全的方式维护凭据,那么获取或拦截访问令牌的可能性有多大?或者,此流程(或可能是另一个 OAuth 流程)中是否包含也包含客户端验证的方法?我意识到客户端已经通过 client_id/client_secret 进行了身份验证,但是当我询问验证时,我询问的是请求的来源(当然假设验证方法不包括检查可以被恶意用户欺骗)。
是否有额外的验证步骤我应该包括我可能错过的东西 - 因为那里有很多信息而且我尽力搜索,但我不能声称我对我所拥有的一切都有深刻的理解到目前为止阅读。
如果我错过了一个额外的验证步骤,它如何适应这个 (client_credentials) 流程?
谢谢, 嘉莉
I've found 2 different ways of using this token to gain access.
- Include the access token in the request header. OR
- Include the access token as a form parameter
这意味着您的访问令牌是 Bearer 令牌类型(因此,您还可以使用第三种方式发送访问令牌:使用带有查询参数的 GET 方法)。
what are the chances that an access token could be obtained or intercepted?
Or, are there methods included in this flow (or perhaps another OAuth flow) that also include client verification?
您有 Bearer 令牌,因此适用 RFC-6750。 威胁缓解 部分回答了您的问题:
首先,您的访问令牌可能会被泄露如果您的客户端应用程序和授权服务器(获取令牌)之间的 TLS 版本,以及之间客户端应用程序和资源服务器(给令牌),存在安全漏洞(摘录:这需要客户端和授权服务器之间的通信交互,以及客户端和授权服务器之间的交互资源服务器,利用机密性和完整性保护。由于 TLS 是强制实施和使用本规范的,因此它是防止令牌通过通信通道泄露的首选方法。)
其次,另一种公开访问令牌的方式是使用 TLS 加速器。如 RFC 的同一部分所述:在某些部署中,包括那些使用负载平衡器的部署,到资源服务器的 TLS 连接在提供资源的实际服务器之前终止。这可能会使令牌在 TLS 连接终止的前端服务器和提供资源的后端服务器之间不受保护。
还有其他方法可以公开访问令牌。
解决方案不是实施另一个 OAuth 流程,而是应用 RFC 第 5.3 节中的建议。作为总结,主要的建议是:
- 始终使用 TLS,
- 验证 TLS 证书链,
- 除了使用 TLS 保护外,还使用令牌加密:例如,使用客户端应用程序和资源服务器之间的共享密钥加密令牌,
- 不要在 cookie 中存储不记名令牌,
- 发行短期不记名令牌,
- 发行范围不记名令牌(使用观众限制)。
这不在 RFC 中,但我会添加此建议:使用相互身份验证。这意味着客户端应用程序必须具有 X.509 证书,该证书必须由资源服务器。这在您选择的特定 Oauth2 流程中是可能的,因为客户端应用程序为资源服务器所知(对于某些替代流程,无法完成)。