CVE-2021-21291 (published 2021-02-02T19:15Z)

OAuth2 Proxy is an open-source reverse proxy and static file server that provides authentication using Providers (Google, GitHub, and others) to validate accounts by email, domain or group. In OAuth2 Proxy before version 7.0.0, for users that use the whitelist domain feature, a domain that ended in a similar way to the intended domain could have been allowed as a redirect. For example, if a whitelist domain was configured for ".example.com", the intention is that subdomains of example.com are allowed. Instead, "example.com" and "badexample.com" could also match. This is fixed in version 7.0.0 onwards. As a workaround, one can disable the whitelist domain feature and run separate OAuth2 Proxy instances for each subdomain.

Severity: MEDIUM
CVSS v2 base score: 5.8 (AV:N/AC:M/Au:N/C:P/I:P/A:N)
CVSS v3 base score: 6.1, MEDIUM (CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N)

Weakness information:
cwe_id: CWE-601
cwe_name: URL Redirection to Untrusted Site ('Open Redirect')
description: A web application accepts a user-controlled input that specifies a link to an external site, and uses that link in a Redirect. This simplifies phishing attacks.
extended_description: An http parameter may contain a URL value and could cause the web application to redirect the request to the specified URL. By modifying the URL value to a malicious site, an attacker may successfully launch a phishing scam and steal user credentials. Because the server name in the modified link is identical to the original site, phishing attempts have a more trustworthy appearance. Whether this issue poses a vulnerability will be subject to the intended behavior of the application. For example, a search engine might intentionally provide redirects to arbitrary URLs.
         

Fix information:
repo_url: https://github.com/oauth2-proxy/oauth2-proxy
commit_details: repo_url: https://github.com/oauth2-proxy/oauth2-proxy
author: Nick Meves
author_date: 2021-02-01 10:04:33-08:00
msg: Merge pull request from GHSA-4mf2-f3wh-gvf2
repository: repo_url: https://github.com/oauth2-proxy/oauth2-proxy
repo_name: oauth2-proxy/oauth2-proxy
description: A reverse proxy that provides authentication with Google, Azure, OpenID Connect and many more identity providers.
repo_language: Go
owner: oauth2-proxy
file_changes: filename: oauthproxy.go
change_type: ModificationType.MODIFY
diff: @@ -437,21 +437,23 @@ func (p *OAuthProxy) IsValidRedirect(redirect string) bool {
 		}
 		redirectHostname := redirectURL.Hostname()
 
-		for _, domain := range p.whitelistDomains {
-			domainHostname, domainPort := splitHostPort(strings.TrimLeft(domain, "."))
-			if domainHostname == "" {
+		for _, allowedDomain := range p.whitelistDomains {
+			allowedHost, allowedPort := splitHostPort(allowedDomain)
+			if allowedHost == "" {
 				continue
 			}
 
-			if (redirectHostname == domainHostname) || (strings.HasPrefix(domain, ".") && strings.HasSuffix(redirectHostname, domainHostname)) {
+			if redirectHostname == strings.TrimPrefix(allowedHost, ".") ||
+				(strings.HasPrefix(allowedHost, ".") &&
+					strings.HasSuffix(redirectHostname, allowedHost)) {
 				// the domain names match, now validate the ports
 				// if the whitelisted domain's port is '*', allow all ports
 				// if the whitelisted domain contains a specific port, only allow that port
 				// if the whitelisted domain doesn't contain a port at all, only allow empty redirect ports ie http and https
 				redirectPort := redirectURL.Port()
-				if (domainPort == "*") ||
-					(domainPort == redirectPort) ||
-					(domainPort == "" && redirectPort == "") {
+				if allowedPort == "*" ||
+					allowedPort == redirectPort ||
+					(allowedPort == "" && redirectPort == "") {
 					return true
 				}
 			}

programming_language: Go
filename: oauthproxy_test.go
change_type: ModificationType.MODIFY
diff: @@ -298,6 +298,11 @@ func TestIsValidRedirect(t *testing.T) {
 			Redirect:       "/\t/\t\\evil.com",
 			ExpectedResult: false,
 		},
+		{
+			Desc:           "openRedirectPartialSubdomain",
+			Redirect:       "http://evilbar.foo",
+			ExpectedResult: false,
+		},
 	}
 
 	for _, tc := range testCases {

programming_language: Go