1. Introduction
1.绪论
OAuth is the industry standard framework for delegated authorization. A lot of thought and care has gone into creating the various flows that make up the standard. Even then, it’s not without vulnerability.
OAuth是委托授权的工业标准框架。在创建构成该标准的各种流程时,我们花了很多心思和精力。即便如此,它也不是没有漏洞的。
In this series of articles, we’ll discuss attacks against OAuth from a theoretical standpoint and describe various options that exist to protect our applications.
在这一系列的文章中,我们将从理论的角度讨论针对OAuth的攻击,并描述现有的各种选项来保护我们的应用程序。
2. The Authorization Code Grant
2.授权代码授予
The Authorization Code Grant flow is the default flow that is used by most applications implementing delegated authorization.
授权代码授予流程是大多数实施委托授权的应用程序所使用的默认流程。
Before that flow begins, the Client must have pre-registered with the Authorization Server, and during this process, it must have also provided a redirection URL — that is, a URL on which the Authorization Server can call back into the Client with an Authorization Code.
在该流程开始之前,客户必须已经在授权服务器上进行了预注册,在此过程中,它还必须提供一个重定向的URL–也就是说,一个授权服务器可以通过授权代码回调到客户的URL。
Let’s take a closer look at how it works and what some of these terms mean.
让我们仔细看看它是如何工作的以及其中一些术语的含义。
During an Authorization Code Grant Flow, a Client (the application that is requesting delegated authorization) redirects the Resource Owner (user) to an Authorization Server (for example, Login with Google). After login, the Authorization Server redirects back to the client with an Authorization Code.
在授权代码授予流程中,客户端(请求委托授权的应用程序)将资源所有者(用户)重定向到授权服务器(例如,用Google登录)。在登录后,授权服务器用一个授权代码重定向回客户端。。
Next, the client calls into an endpoint at the Authorization Server, requesting an Access Token by providing the Authorization Code. At this point, the flow ends, and the client can use the token to access resources protected by the Authorization Server.
接下来,客户端调用授权服务器的一个端点,通过提供授权码请求访问令牌。在这一点上,流程结束,客户可以使用令牌来访问受授权服务器保护的资源。
Now, the OAuth 2.0 Framework allows for these Clients to be public, say in scenarios where the Client can’t safely hold onto a Client Secret. Let’s take a look at some redirection attacks that are possible against Public Clients.
现在,OAuth 2.0框架允许这些客户端是公开的,例如在客户端不能安全地持有客户端秘密的情况下。让我们来看看一些可能针对公共客户端的重定向攻击。
3. Redirection Attacks
3.重定向攻击
3.1. Attack Preconditions
3.1.攻击的先决条件
Redirection attacks rely on the fact that the OAuth standard doesn’t fully describe the extent to which this redirect URL must be specified. This is by design.
重定向攻击依赖于这样一个事实:OAuth标准并没有完全描述必须指定这个重定向URL的程度。这是个设计。
This allows some implementations of the OAuth protocol to allow for a partial redirect URL.
这允许OAuth协议的某些实现允许部分重定向URL。
For example, if we register a Client ID and a Client Redirect URL with the following wildcard-based match against an Authorization Server:
例如,如果我们注册一个客户ID和一个客户重定向URL,并对授权服务器进行以下基于通配符的匹配。
*.cloudapp.net
*.cloudapp.net。
This would be valid for:
这将对以下情况有效。
app.cloudapp.net
app.cloudapp.net。
but also for:
但也为。
evil.cloudapp.net
evil.cloudapp.net。
We’ve selected the cloudapp.net domain on purpose, as this is a real location where we can host OAuth-powered applications. The domain is a part of Microsoft’s Windows Azure platform and allows any developer to host a subdomain under it to test an application. This in itself is not a problem, but it’s a vital part of the greater exploit.
我们特意选择了cloudapp.net域,因为这是一个可以托管OAuth驱动的应用程序的真实位置。该域是Microsoft的Windows Azure平台的一部分,允许任何开发人员在其下托管一个子域以测试应用程序。这本身并不是一个问题,但它是更大的漏洞的一个重要部分。
The second part of this exploit is an Authorization Server that allows wildcard matching on callback URLs.
这个漏洞的第二部分是一个授权服务器,允许对回调的URL进行通配符匹配。
Finally, to realize this exploit, the application developer needs to register with the Authorization server to accept any URL under the main domain, in the form *.cloudapp.net.
最后,为了实现这个漏洞,应用程序开发人员需要向授权服务器注册,接受主域下的任何URL,形式为*.cloudapp.net。
3.2. The Attack
3.2.攻击
When these conditions are met, the attacker then needs to trick the user into launching a page from the subdomain under his control, by for example, sending the user an authentic looking email asking him to take some action on the account protected by OAuth. Typically, this would look something like https://evil.cloudapp.net/login. When the user opens this link and selects login, he will be redirected to the Authorization Server with an authorization request:
当这些条件得到满足时,攻击者就需要欺骗用户从他控制的子域中启动一个页面,例如,向用户发送一封看起来很真实的电子邮件,要求他对受OAuth保护的账户采取一些行动。通常情况下,这看起来就像https://evil.cloudapp.net/login。当用户打开这个链接并选择登录时,他将被重定向到授权服务器并发出授权请求。
GET /authorize?response_type=code&client_id={apps-client-id}&state={state}&redirect_uri=https%3A%2F%2Fevil.cloudapp.net%2Fcb HTTP/1.1
While this may look typical, this URL is malicious. See, in this case, the Authorization Server receives a doctored URL with the app’s Client ID and a redirection URL pointing back to evil’s app.
虽然这可能看起来很典型,但这个URL是恶意的。请看,在这种情况下,授权服务器收到了一个带有应用程序客户端ID的篡改的URL,以及一个指向邪恶的应用程序的重定向URL。
The Authorization Server will then validate the URL, which is a subdomain under the specified main domain. Since the Authorization Server believes that the request originated from a valid source, it will authenticate the user and then ask for consent as it would do normally.
然后,授权服务器将验证该URL,它是指定主域下的一个子域。由于授权服务器相信该请求来自一个有效的来源,它将对用户进行验证,然后像正常情况下那样征求同意。
After this is done, it will now redirect back into the evil.cloudapp.net subdomain, handing the Authorization Code to the attacker.
完成后,它现在将重定向到evil.cloudapp.net子域,将授权码交给攻击者。
Since the attacker now has the Authorization Code, all he needs to do is to call the token endpoint of the Authorization Server with the Authorization Code to receive a token, which allows him access to the Resource Owner’s protected resources.
由于攻击者现在有了授权码,他所需要做的就是用授权码调用授权服务器的令牌端点,以获得一个令牌,这允许他访问资源所有者的受保护资源。
4. Spring OAuth Authorization Server Vulnerability Assessment
4.Spring OAuth授权服务器漏洞评估
Let’s take a look at a simple Spring OAuth Authorization Server configuration:
让我们来看看一个简单的Spring OAuth授权服务器配置。
@Configuration
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("apricot-client-id")
.authorizedGrantTypes("authorization_code")
.scopes("scope1", "scope2")
.redirectUris("https://app.cloudapp.net/oauth");
}
// ...
}
We can see here that the Authorization Server is configuring a new client with the id “apricot-client-id”. There is no client secret, so this is a Public Client.
我们在这里可以看到,授权服务器正在配置一个新的客户,其ID为“apricot-client-id”。没有客户秘密,所以这是一个公共客户。
Our security ears should perk up at this, as we now have two out of the three conditions – evil people can register subdomains and we are using a Public Client.
我们的安全耳朵应该对此感到兴奋,因为我们现在具备了三个条件中的两个–邪恶的人可以注册子域我们正在使用公共客户端。
But, note that we are configuring the redirect URL here too and that it’s absolute. We can mitigate the vulnerability by doing so.
但是,请注意,我们在这里也配置了重定向的URL,而且是绝对的。我们可以通过这样做来缓解这个漏洞。
4.1. Strict
4.1.严格的
By default, Spring OAuth allows a certain degree of flexibility in redirect URL matching.
默认情况下,Spring OAuth允许在重定向URL匹配方面有一定程度的灵活性。
For example, the DefaultRedirectResolver supports subdomain matching.
例如,DefaultRedirectResolver支持子域匹配。
Let’s only use what we need. And if we can just exactly match the redirect URL, we should do:
让我们只使用我们需要的东西。而如果我们能完全匹配重定向的URL,我们应该做的。
@Configuration
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
//...
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
endpoints.redirectResolver(new ExactMatchRedirectResolver());
}
}
In this case, we’ve switched to using the ExactMatchRedirectResolver for redirect URLs. This resolver does an exact string match, without parsing the redirect URL in any way. This makes its behavior far more secure and certain.
在这种情况下,我们改用ExactMatchRedirectResolver来处理重定向URL。这个解析器进行精确的字符串匹配,而不以任何方式解析重定向URL。这使其行为更加安全和确定。
4.2. Lenient
4.2 宽松
We can find the default code that deals with redirect URL matching in the Spring Security OAuth source:
我们可以在Spring Security OAuth源中找到处理重定向URL匹配的默认代码。
/**
Whether the requested redirect URI "matches" the specified redirect URI. For a URL, this implementation tests if
the user requested redirect starts with the registered redirect, so it would have the same host and root path if
it is an HTTP URL. The port, userinfo, query params also matched. Request redirect uri path can include
additional parameters which are ignored for the match
<p>
For other (non-URL) cases, such as for some implicit clients, the redirect_uri must be an exact match.
@param requestedRedirect The requested redirect URI.
@param redirectUri The registered redirect URI.
@return Whether the requested redirect URI "matches" the specified redirect URI.
*/
protected boolean redirectMatches(String requestedRedirect, String redirectUri) {
UriComponents requestedRedirectUri = UriComponentsBuilder.fromUriString(requestedRedirect).build();
UriComponents registeredRedirectUri = UriComponentsBuilder.fromUriString(redirectUri).build();
boolean schemeMatch = isEqual(registeredRedirectUri.getScheme(), requestedRedirectUri.getScheme());
boolean userInfoMatch = isEqual(registeredRedirectUri.getUserInfo(), requestedRedirectUri.getUserInfo());
boolean hostMatch = hostMatches(registeredRedirectUri.getHost(), requestedRedirectUri.getHost());
boolean portMatch = matchPorts ? registeredRedirectUri.getPort() == requestedRedirectUri.getPort() : true;
boolean pathMatch = isEqual(registeredRedirectUri.getPath(),
StringUtils.cleanPath(requestedRedirectUri.getPath()));
boolean queryParamMatch = matchQueryParams(registeredRedirectUri.getQueryParams(),
requestedRedirectUri.getQueryParams());
return schemeMatch && userInfoMatch && hostMatch && portMatch && pathMatch && queryParamMatch;
}
We can see that the URL matching is done by parsing the incoming redirect URL into its component parts. This is quite complex due to its several features, like whether the port, subdomain, and query parameters should match. And choosing to allow subdomain matches is something to think twice about.
我们可以看到,URL匹配是通过将传入的重定向URL解析成其组成部分来完成的。这是很复杂的,因为它有几个特点,比如端口、子域和查询参数是否应该匹配。而选择允许子域匹配是需要三思的。
Of course, this flexibility is there, if we need it – let’s just use it with caution.
当然,如果我们需要的话,这种灵活性是存在的–只是让我们谨慎地使用它。
5. Implicit Flow Redirect Attacks
5.隐性流量重定向攻击
To be clear, the Implicit Flow isn’t recommended. It’s much better to use the Authorization Code Grant flow with additional security provided by PKCE. That said, let’s take a look at how a redirect attack manifests with the implicit flow.
明确地说,隐式流程不推荐使用。使用授权代码授予流程要好得多,该流程由PKCE>提供额外的安全性。也就是说,让我们来看看使用隐式流程的重定向攻击是如何表现的。
A redirect attack against an implicit flow would follow the same basic outline as we’ve seen above. The main difference is that the attacker gets the token immediately, as there is no authorization code exchange step.
针对隐式流程的重定向攻击将遵循我们在上面看到的相同的基本纲要。主要的区别是,攻击者立即得到令牌,因为没有授权代码交换步骤。
As before, an absolute matching of the redirect URL will mitigate this class of attack as well.
和以前一样,绝对匹配的重定向URL也会缓解这类攻击。
Furthermore, we can find that the implicit flow contains another related vulnerability. An attacker can use a client as an open redirector and get it to reattach fragments.
此外,我们可以发现,隐含流包含另一个相关的漏洞。攻击者可以使用客户端作为一个开放的重定向器,并让它重新连接片段。
The attack begins as before, with an attacker getting the user to visit a page under the attacker’s control, for example, https://evil.cloudapp.net/info. The page is crafted to initiate an authorization request as before. However, it now includes a redirect URL:
攻击开始时和以前一样,攻击者让用户访问一个由攻击者控制的页面,例如,https://evil.cloudapp.net/info。这个页面像以前一样被设计成发起一个授权请求。然而,它现在包括一个重定向URL。
GET /authorize?response_type=token&client_id=ABCD&state=xyz&redirect_uri=https%3A%2F%2Fapp.cloudapp.net%2Fcb%26redirect_to
%253Dhttps%253A%252F%252Fevil.cloudapp.net%252Fcb HTTP/1.1
The redirect_to https://evil.cloudapp.net is setting up the Authorization Endpoint to redirect the token to a domain under the attacker’s control. The authorization server will now first redirect to the actual app site:
redirect_to https://evil.cloudapp.net正在设置授权端点,将令牌重定向到攻击者控制的域中。授权服务器现在将首先重定向到实际的应用程序站点。
Location: https://app.cloudapp.net/cb?redirect_to%3Dhttps%3A%2F%2Fevil.cloudapp.net%2Fcb#access_token=LdKgJIfEWR34aslkf&...
When this request arrives at the open redirector, it will extract the redirect URL evil.cloudapp.net and then redirect to the attacker’s site:
当这个请求到达开放重定向器时,它将提取重定向URL evil.cloudapp.net,然后重定向到攻击者的网站。
https://evil.cloudapp.net/cb#access_token=LdKgJIfEWR34aslkf&...
Absolute URL matching will mitigate this attack, too.
绝对的URL匹配也会减轻这种攻击。
6. Summary
6.归纳总结
In this article, we’ve discussed a class of attacks against the OAuth protocol that are based on redirection URLs.
在这篇文章中,我们已经讨论了一类针对OAuth协议的攻击,这些攻击是基于重定向URL的。
While this has potentially serious consequences, using absolute URL matching at the Authorization Server mitigates this class of attack.
虽然这有潜在的严重后果,但在授权服务器上使用绝对的URL匹配可以缓解这类攻击。