1. 簡介
OAuth 是授權委託的行業標準框架。 制定各種流程需要投入大量思考和精力。 即使如此,它仍然存在漏洞。
在本文檔系列中,我們將從理論角度探討對 OAuth 的攻擊,並描述各種保護應用程序的方法。
2. 授權碼流程
授權碼流程 是大多數實現委託授權的應用所使用的默認流程。
在流程開始之前,客户端必須已在授權服務器上進行預註冊,並且在此過程中,它也必須提供一個重定向 URL——即,一個授權服務器可以回呼到客户端並提供授權碼的 URL
讓我們更詳細地瞭解它的工作原理以及這些術語的含義。
在授權碼流程中,客户端(即請求委託授權的應用)會將資源擁有者(用户)重定向到授權服務器(例如,使用 Google 登錄)。登錄後,授權服務器 授權服務器在用户登錄後,將授權碼回傳給客户端) 將客户端重定向回,並提供授權碼。
然後,客户端調用授權服務器上的一個端點,通過提供授權碼來請求訪問令牌。此時,流程結束,客户端可以使用令牌來訪問授權服務器保護的資源。
現在,OAuth 2.0 框架允許客户端為公共客户端而設計,例如在客户端無法安全地持有客户端密鑰的情況下,讓我們看看對公共客户端可能發生的重定向攻擊。
3. 重定向攻擊
Redirection attacks exploit vulnerabilities in web applications that allow an attacker to redirect a user to a malicious website. These attacks typically involve manipulating HTTP requests to bypass security measures and trick the user into entering sensitive information or downloading malware.
Types of Redirection Attacks:
- HTTP Redirect Chains: An attacker crafts a series of HTTP redirects, each leading to a different malicious website. The user is unknowingly guided through a chain of redirects, ultimately landing on a compromised site.
- URL Redirection Exploitation: Attackers manipulate URL parameters to redirect users to a malicious website. This can be achieved through techniques like URL rewriting or manipulating form submissions.
- Phishing Attacks: Redirection attacks are frequently used in conjunction with phishing attacks. Attackers redirect users to a fake login page that mimics a legitimate website, allowing them to steal usernames and passwords.
Mitigation Strategies:
- Input Validation: Implement strict input validation to prevent malicious URLs from being used in HTTP requests.
- Output Encoding: Properly encode output to prevent cross-site scripting (XSS) vulnerabilities, which can be exploited to redirect users.
- Web Application Firewalls (WAFs): Deploy WAFs to detect and block malicious HTTP requests.
- Regular Security Audits: Conduct regular security audits to identify and address potential vulnerabilities.
3.1. 攻擊前提條件
重定向攻擊依賴於 OAuth 標準並未完全描述重定向 URL 必須指定的程度這一事實。 這也是有意為之。
這允許某些 OAuth 協議實現允許使用部分重定向 URL。
例如,如果我們使用以下基於通配符的匹配方式向授權服務器註冊客户端 ID 和客户端重定向 URL:
*.cloudapp.net
這將有效用於:
app.cloudapp.net
但也會有效用於:
evil.cloudapp.net
我們故意選擇 cloudapp.net 域名,因為這是一個真實的託管 OAuth 應用程序的位置。 域名是 Microsoft Azure 平台的一部分 (Windows Azure 平台),允許任何開發人員在其下注冊子域名以測試應用程序。 這一本身不是問題,但它是更大漏洞的關鍵組成部分。
漏洞的第二部分是允許在回調 URL 上進行通配符匹配的授權服務器。
要實現這一漏洞,應用程序開發人員需要與授權服務器註冊,以接受主域名下的任何 URL,格式為 *.cloudapp.net。
3.2. 攻擊
當滿足上述條件時,攻擊者需要誘騙用户從他控制的子域名發起頁面,例如,通過向用户發送一個看起來真實的郵件,要求用户在 OAuth 保護的賬户上執行某些操作。通常,這會像這樣:<em https://evil.cloudapp.net/login</em>。當用户打開此鏈接並選擇登錄時,他將被重定向到授權服務器,並提交一個授權請求。
GET /authorize?response_type=code&client_id={apps-client-id}&state={state}&redirect_uri=https%3A%2F%2Fevil.cloudapp.net%2Fcb HTTP/1.1雖然這看起來很正常,但這個URL是惡意的。可以看到,在這種情況中,授權服務器接收到一個被篡改的URL,其中包含應用程序的客户端ID,以及指向攻擊者應用程序的重定向URL。
授權服務器會驗證該URL,該URL是指定主域下的一個子域名。由於授權服務器認為請求來自一個有效的來源,它會驗證用户身份,然後按照正常流程請求同意。
完成這些操作後,它會重定向回evil.cloudapp.net子域名,並將授權碼交給攻擊者。
由於攻擊者現在擁有授權碼,他只需要調用授權服務器的令牌端點,並使用授權碼來接收令牌,從而允許他訪問資源所有者受保護的資源。
4. Spring OAuth 授權服務器漏洞評估
讓我們來看一個簡單的 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");
}
// ...
}我們可以看到這裏,授權服務器正在為客户端配置一個新客户端,其id是 “apricot-client-id”。 客户端沒有密鑰,因此這是一個公共客户端。
我們的安全警惕應該在此提高,因為我們現在滿足了三個條件中的兩個——惡意行為者可以註冊子域名 並且我們正在使用公共客户端。
但是,請注意,我們正在配置 重定向URL也,並且它是絕對的,通過這樣做,我們可以緩解漏洞。
4.1. 嚴格匹配
Spring OAuth 默認允許在重定向 URL 匹配中具有一定的靈活性。
例如,<em >DefaultRedirectResolver</em> 支持子域名匹配。
只使用我們需要的即可。 如果我們能夠精確匹配重定向 URL,則應這樣做:
@Configuration
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
//...
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
endpoints.redirectResolver(new ExactMatchRedirectResolver());
}
}在這種情況下,我們已切換到使用 ExactMatchRedirectResolver 作為重定向 URL 的解析器。該解析器進行精確的字符串匹配,不以任何方式解析重定向 URL。 這使得它的行為更加安全且可確定。
4.2. 容錯性 (Lenient)
我們可以從 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;
}我們能看出,URL匹配是通過解析傳入的重定向URL將其分解成各個組成部分來實現的。由於其諸多特性,這本身就相當複雜,例如,端口、子域名和查詢參數是否匹配等問題。 並且,選擇允許子域名匹配需要慎重考慮。
當然,這種靈活性是存在的,如果我們需要它,我們只需謹慎使用。
5. 隱式流重定向攻擊
值得注意的是,隱式流不建議使用。 使用帶有額外安全保障的授權碼流程(Authorization Code Grant flow)更好。這通過PKCE實現。儘管如此,我們還是來看看重定向攻擊如何以隱式流中出現。
針對隱式流的重定向攻擊將遵循我們上面所見的基本流程。主要區別在於,攻擊者會立即獲得令牌,因為沒有授權碼交換步驟。
正如之前所述,絕對匹配重定向 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
將 redirect_to https://evil.cloudapp.net 設置為 Authorization Endpoint,將令牌重定向到攻擊者控制的域名。授權服務器現在將首先重定向到實際應用站點:
Location: https://app.cloudapp.net/cb?redirect_to%3Dhttps%3A%2F%2Fevil.cloudapp.net%2Fcb#access_token=LdKgJIfEWR34aslkf&...
當此請求到達開放重定向器時,它將提取重定向 URL evil.cloudapp.net,然後重定向到攻擊者的網站:
https://evil.cloudapp.net/cb#access_token=LdKgJIfEWR34aslkf&...
絕對URL匹配也將緩解此攻擊。
6. 摘要
本文討論了針對 OAuth 協議的一類基於重定向 URL 的攻擊。
儘管這種攻擊可能造成嚴重後果,但使用授權服務器上的絕對 URL 匹配可以緩解這種攻擊。