VYPR
Moderate severityNVD Advisory· Published Jun 25, 2018· Updated Sep 16, 2024

CVE-2018-11041

CVE-2018-11041

Description

Cloud Foundry UAA, versions later than 4.6.0 and prior to 4.19.0 except 4.10.1 and 4.7.5 and uaa-release versions later than v48 and prior to v60 except v55.1 and v52.9, does not validate redirect URL values on a form parameter used for internal UAA redirects on the login page, allowing open redirects. A remote attacker can craft a malicious link that, when clicked, will redirect users to arbitrary websites after a successful login attempt.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

Cloud Foundry UAA fails to validate the redirect URL on the login page, allowing an open redirect after a successful login.

Vulnerability

Cloud Foundry UAA version later than 4.6.0 and prior to 4.19.0 (except 4.10.1 and 4.7.5) and uaa-release versions later than v48 and prior to v60 (except v55.1 and v52.9) do not validate the form_redirect_uri parameter on the login page, enabling an open redirect vulnerability [2]. The UAA server performs internal redirects after authentication, but fails to check if the target URL belongs to an allowed domain [1].

Exploitation

A remote attacker crafts a malicious link that points to a legitimate UAA login page but includes a crafted form_redirect_uri parameter targeting an external site [2]. When a victim clicks this link and completes a successful login, the server redirects the victim’s browser to the attacker-controlled external URL. No additional authentication or privileges are required beyond the ability to host a link and the victim’s willing click [2].

Impact

A successful open redirect allows an attacker to direct users to arbitrary external websites after authentication. This can be leveraged for phishing attacks, where users believe they are still within the Cloud Foundry environment, potentially leading to credential theft or malware installation. The redirect occurs in the user’s browser after a legitimate login, giving the attack a veneer of authenticity [2].

Mitigation

The vulnerability is fixed in UAA versions 4.10.1, 4.7.5, and 4.19.0, and in uaa-release versions v55.1 and v60 [2]. The fix adds validation of the redirect URL against the server’s expected hostname before saving the request [3][4]. Operators should upgrade to the latest patched version or apply the fix from the referenced commits. No workaround is available [2]. Not listed in CISA KEV.

AI Insight generated on May 22, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
org.cloudfoundry.identity:cloudfoundry-identity-serverMaven
< 4.7.54.7.5
org.cloudfoundry.identity:cloudfoundry-identity-serverMaven
>= 4.8.0, < 4.10.14.10.1
org.cloudfoundry.identity:cloudfoundry-identity-serverMaven
>= 4.11.0, < 4.12.34.12.3
org.cloudfoundry.identity:cloudfoundry-identity-serverMaven
>= 4.13.0, < 4.19.04.19.0

Affected products

2

Patches

8
d17b23fc3bf9

Request cache only saves requests with form_redirect_uri if it's valid

https://github.com/cloudfoundry/uaaJaskanwal PawarJun 14, 2018via ghsa
5 files changed · +61 19
  • server/src/main/java/org/cloudfoundry/identity/uaa/util/UaaUrlUtils.java+13 0 modified
    @@ -219,4 +219,17 @@ public static String getRequestPath(HttpServletRequest request) {
             String path = String.format("%s%s", servletPath, pathInfo);
             return path;
         }
    +
    +    public static boolean uriHasMatchingHost(String uri, String hostname) {
    +        if (uri == null) {
    +            return false;
    +        }
    +
    +        try {
    +            URL url = new URL(uri);
    +            return hostname.equals(url.getHost());
    +        } catch (MalformedURLException e) {
    +            return false;
    +        }
    +    }
     }
    
  • server/src/main/java/org/cloudfoundry/identity/uaa/web/UaaSavedRequestAwareAuthenticationSuccessHandler.java+2 16 modified
    @@ -17,12 +17,11 @@
     
     import org.apache.commons.logging.Log;
     import org.apache.commons.logging.LogFactory;
    +import org.cloudfoundry.identity.uaa.util.UaaUrlUtils;
     import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
     
     import javax.servlet.http.HttpServletRequest;
     import javax.servlet.http.HttpServletResponse;
    -import java.net.MalformedURLException;
    -import java.net.URL;
     
     public class UaaSavedRequestAwareAuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {
         public static final String SAVED_REQUEST_SESSION_ATTRIBUTE = "SPRING_SECURITY_SAVED_REQUEST";
    @@ -40,23 +39,10 @@ public String determineTargetUrl(HttpServletRequest request, HttpServletResponse
             if (redirectAttribute !=null) {
                 logger.debug("Returning redirectAttribute saved URI:"+redirectAttribute);
                 return (String) redirectAttribute;
    -        } else if (isApprovedFormRedirectUri(request, redirectFormParam)) {
    +        } else if (UaaUrlUtils.uriHasMatchingHost(redirectFormParam, request.getServerName())) {
                 return redirectFormParam;
             } else {
                 return super.determineTargetUrl(request, response);
             }
         }
    -
    -    private boolean isApprovedFormRedirectUri(HttpServletRequest request, String redirectUri) {
    -        if (redirectUri == null) {
    -            return false;
    -        }
    -
    -        try {
    -            URL url = new URL(redirectUri);
    -            return request.getServerName().equals(url.getHost());
    -        } catch (MalformedURLException e) {
    -            return false;
    -        }
    -    }
     }
    
  • server/src/main/java/org/cloudfoundry/identity/uaa/web/UaaSavedRequestCache.java+3 1 modified
    @@ -92,7 +92,9 @@ protected boolean shouldSaveFormRedirectParameter(HttpServletRequest request) {
             if (StringUtils.isEmpty(formRedirect)) {
                 return false;
             }
    -
    +        if (!UaaUrlUtils.uriHasMatchingHost(formRedirect, request.getServerName())) {
    +            return false;
    +        }
             if (hasSavedRequest(request)) {
                 return false;
             }
    
  • server/src/test/java/org/cloudfoundry/identity/uaa/util/UaaUrlUtilsTest.java+15 0 modified
    @@ -32,8 +32,10 @@
     import static org.hamcrest.CoreMatchers.is;
     import static org.hamcrest.Matchers.equalTo;
     import static org.junit.Assert.assertEquals;
    +import static org.junit.Assert.assertFalse;
     import static org.junit.Assert.assertNotNull;
     import static org.junit.Assert.assertThat;
    +import static org.junit.Assert.assertTrue;
     import static org.junit.Assert.fail;
     
     public class UaaUrlUtilsTest {
    @@ -360,6 +362,19 @@ public void test_validate_invalid_redirect_uri() {
             validateRedirectUri(convertToHttps(invalidHttpWildCardUrls), false);
         }
     
    +    @Test
    +    public void testUriHasMatchingHost() {
    +        assertTrue(UaaUrlUtils.uriHasMatchingHost("http://test.com/test", "test.com"));
    +        assertTrue(UaaUrlUtils.uriHasMatchingHost("http://subdomain.test.com/test", "subdomain.test.com"));
    +        assertTrue(UaaUrlUtils.uriHasMatchingHost("http://1.2.3.4/test", "1.2.3.4"));
    +
    +        assertFalse(UaaUrlUtils.uriHasMatchingHost(null, "test.com"));
    +        assertFalse(UaaUrlUtils.uriHasMatchingHost("http://not-test.com/test", "test.com"));
    +        assertFalse(UaaUrlUtils.uriHasMatchingHost("not-valid-url", "test.com"));
    +        assertFalse(UaaUrlUtils.uriHasMatchingHost("http://1.2.3.4/test", "test.com"));
    +        assertFalse(UaaUrlUtils.uriHasMatchingHost("http://test.com/test", "1.2.3.4"));
    +    }
    +
         private void validateRedirectUri(List<String> urls, boolean result) {
             Map<String, String> failed = getFailedUrls(urls, result);
             if (!failed.isEmpty()) {
    
  • server/src/test/java/org/cloudfoundry/identity/uaa/web/UaaSavedRequestCacheTests.java+28 2 modified
    @@ -28,8 +28,13 @@
     import org.springframework.security.web.savedrequest.SavedRequest;
     
     import javax.servlet.FilterChain;
    +import javax.servlet.ServletException;
     import javax.servlet.ServletResponse;
    +import javax.servlet.http.HttpServletRequest;
     import javax.servlet.http.HttpSession;
    +import java.io.IOException;
    +import java.net.MalformedURLException;
    +import java.net.URL;
     
     import static org.cloudfoundry.identity.uaa.web.UaaSavedRequestAwareAuthenticationSuccessHandler.FORM_REDIRECT_PARAMETER;
     import static org.cloudfoundry.identity.uaa.web.UaaSavedRequestAwareAuthenticationSuccessHandler.SAVED_REQUEST_SESSION_ATTRIBUTE;
    @@ -38,6 +43,7 @@
     import static org.junit.Assert.assertFalse;
     import static org.junit.Assert.assertNotNull;
     import static org.junit.Assert.assertTrue;
    +import static org.mockito.ArgumentMatchers.any;
     import static org.mockito.Matchers.anyObject;
     import static org.mockito.Matchers.anyString;
     import static org.mockito.Mockito.mock;
    @@ -103,6 +109,7 @@ public void filter_saves_when_needed() throws Exception {
             request.setPathInfo("/login.do");
             request.setRequestURI("/login.do");
             request.setParameter(FORM_REDIRECT_PARAMETER, redirectUri);
    +        request.setServerName(new URL(redirectUri).getHost());
             assertTrue(cache.shouldSaveFormRedirectParameter(request));
             ServletResponse response = new MockHttpServletResponse();
     
    @@ -145,8 +152,11 @@ public void saveFormRedirectRequest_GET_Method() throws Exception {
     
         @Test
         public void saveFormRedirectRequest() throws Exception {
    +        String redirectUri = "http://login";
             request.setSession(session);
    -        request.setParameter(FORM_REDIRECT_PARAMETER, "http://login");
    +        request.setParameter(FORM_REDIRECT_PARAMETER, redirectUri);
    +        request.setServerName(new URL(redirectUri).getHost());
    +
             spy.saveRequest(request, new MockHttpServletResponse());
             verify(spy).saveClientRedirect(request, request.getParameter(FORM_REDIRECT_PARAMETER));
         }
    @@ -169,14 +179,19 @@ public void only_save_for_POST_calls() {
         }
     
         @Test
    -    public void should_save_condition_works() {
    +    public void should_save_condition_works() throws MalformedURLException {
             assertFalse(cache.shouldSaveFormRedirectParameter(request));
    +
             request.setPathInfo("/login.do");
             assertFalse(cache.shouldSaveFormRedirectParameter(request));
    +
             request.setParameter(FORM_REDIRECT_PARAMETER, redirectUri);
    +        request.setServerName(new URL(redirectUri).getHost());
             assertTrue(cache.shouldSaveFormRedirectParameter(request));
    +
             request.setSession(session);
             assertTrue(cache.shouldSaveFormRedirectParameter(request));
    +
             ClientRedirectSavedRequest savedRequest = new ClientRedirectSavedRequest(request, redirectUri);
             session.setAttribute(SAVED_REQUEST_SESSION_ATTRIBUTE, savedRequest);
             assertFalse(cache.shouldSaveFormRedirectParameter(request));
    @@ -215,5 +230,16 @@ public void saved_request_matcher() {
     
         }
     
    +    @Test
    +    public void unapprovedFormRedirectRequestDoesNotSave() throws IOException, ServletException {
    +        request.setPathInfo("/login.do");
    +        request.setRequestURI("/login.do");
    +        request.setMethod(HttpMethod.POST.name());
    +        request.setParameter(FORM_REDIRECT_PARAMETER, "http://test.com");
    +        request.setServerName("not-test.com");
    +
    +        spy.doFilter(request, new MockHttpServletResponse(), mock(FilterChain.class));
     
    +        verify(spy, never()).saveClientRedirect(any(HttpServletRequest.class), anyString());
    +    }
     }
    \ No newline at end of file
    
57a15dfb7e0e

Validate form_redirect_uri parameter against the request host.

https://github.com/cloudfoundry/uaaJaskanwal PawarJun 14, 2018via ghsa
2 files changed · +33 8
  • server/src/main/java/org/cloudfoundry/identity/uaa/web/UaaSavedRequestAwareAuthenticationSuccessHandler.java+16 1 modified
    @@ -21,6 +21,8 @@
     
     import javax.servlet.http.HttpServletRequest;
     import javax.servlet.http.HttpServletResponse;
    +import java.net.MalformedURLException;
    +import java.net.URL;
     
     public class UaaSavedRequestAwareAuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {
         public static final String SAVED_REQUEST_SESSION_ATTRIBUTE = "SPRING_SECURITY_SAVED_REQUEST";
    @@ -38,10 +40,23 @@ public String determineTargetUrl(HttpServletRequest request, HttpServletResponse
             if (redirectAttribute !=null) {
                 logger.debug("Returning redirectAttribute saved URI:"+redirectAttribute);
                 return (String) redirectAttribute;
    -        } else if (redirectFormParam != null) {
    +        } else if (isApprovedFormRedirectUri(request, redirectFormParam)) {
                 return redirectFormParam;
             } else {
                 return super.determineTargetUrl(request, response);
             }
         }
    +
    +    private boolean isApprovedFormRedirectUri(HttpServletRequest request, String redirectUri) {
    +        if (redirectUri == null) {
    +            return false;
    +        }
    +
    +        try {
    +            URL url = new URL(redirectUri);
    +            return request.getServerName().equals(url.getHost());
    +        } catch (MalformedURLException e) {
    +            return false;
    +        }
    +    }
     }
    
  • server/src/test/java/org/cloudfoundry/identity/uaa/web/UaaSavedRequestAwareAuthenticationSuccessHandlerTests.java+17 7 modified
    @@ -41,16 +41,26 @@ public void allow_url_override() {
             assertEquals("http://test.com", handler.determineTargetUrl(request, new MockHttpServletResponse()));
         }
     
    -    @Test
    -    public void form_parameter_works() {
    -        request.setParameter(FORM_REDIRECT_PARAMETER, "http://test.com");
    -        assertEquals("http://test.com", handler.determineTargetUrl(request, new MockHttpServletResponse()));
    -    }
    -
         @Test
         public void form_parameter_is_overridden() {
             request.setParameter(FORM_REDIRECT_PARAMETER, "http://test.com");
             request.setAttribute(URI_OVERRIDE_ATTRIBUTE, "http://override.test.com");
             assertEquals("http://override.test.com", handler.determineTargetUrl(request, new MockHttpServletResponse()));
         }
    -}
    \ No newline at end of file
    +
    +    @Test
    +    public void validFormRedirectIsReturned() {
    +        String redirectUri = request.getScheme() + "://" + request.getServerName() + "/test";
    +
    +        request.setParameter(FORM_REDIRECT_PARAMETER, redirectUri);
    +        assertEquals(redirectUri, handler.determineTargetUrl(request, new MockHttpServletResponse()));
    +    }
    +
    +    @Test
    +    public void invalidFormRedirectIsNotReturned() {
    +        String redirectUri = "http://test.com/test";
    +
    +        request.setParameter(FORM_REDIRECT_PARAMETER, redirectUri);
    +        assertEquals("/", handler.determineTargetUrl(request, new MockHttpServletResponse()));
    +    }
    +}
    
7d750e036cd5

Validate form_redirect_uri parameter against the request host.

https://github.com/cloudfoundry/uaaJennifer HamonJun 13, 2018via ghsa
2 files changed · +33 8
  • server/src/main/java/org/cloudfoundry/identity/uaa/web/UaaSavedRequestAwareAuthenticationSuccessHandler.java+16 1 modified
    @@ -21,6 +21,8 @@
     
     import javax.servlet.http.HttpServletRequest;
     import javax.servlet.http.HttpServletResponse;
    +import java.net.MalformedURLException;
    +import java.net.URL;
     
     public class UaaSavedRequestAwareAuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {
         public static final String SAVED_REQUEST_SESSION_ATTRIBUTE = "SPRING_SECURITY_SAVED_REQUEST";
    @@ -38,10 +40,23 @@ public String determineTargetUrl(HttpServletRequest request, HttpServletResponse
             if (redirectAttribute !=null) {
                 logger.debug("Returning redirectAttribute saved URI:"+redirectAttribute);
                 return (String) redirectAttribute;
    -        } else if (redirectFormParam != null) {
    +        } else if (isApprovedFormRedirectUri(request, redirectFormParam)) {
                 return redirectFormParam;
             } else {
                 return super.determineTargetUrl(request, response);
             }
         }
    +
    +    private boolean isApprovedFormRedirectUri(HttpServletRequest request, String redirectUri) {
    +        if (redirectUri == null) {
    +            return false;
    +        }
    +
    +        try {
    +            URL url = new URL(redirectUri);
    +            return request.getServerName().equals(url.getHost());
    +        } catch (MalformedURLException e) {
    +            return false;
    +        }
    +    }
     }
    
  • server/src/test/java/org/cloudfoundry/identity/uaa/web/UaaSavedRequestAwareAuthenticationSuccessHandlerTests.java+17 7 modified
    @@ -41,16 +41,26 @@ public void allow_url_override() {
             assertEquals("http://test.com", handler.determineTargetUrl(request, new MockHttpServletResponse()));
         }
     
    -    @Test
    -    public void form_parameter_works() {
    -        request.setParameter(FORM_REDIRECT_PARAMETER, "http://test.com");
    -        assertEquals("http://test.com", handler.determineTargetUrl(request, new MockHttpServletResponse()));
    -    }
    -
         @Test
         public void form_parameter_is_overridden() {
             request.setParameter(FORM_REDIRECT_PARAMETER, "http://test.com");
             request.setAttribute(URI_OVERRIDE_ATTRIBUTE, "http://override.test.com");
             assertEquals("http://override.test.com", handler.determineTargetUrl(request, new MockHttpServletResponse()));
         }
    -}
    \ No newline at end of file
    +
    +    @Test
    +    public void validFormRedirectIsReturned() {
    +        String redirectUri = request.getScheme() + "://" + request.getServerName() + "/test";
    +
    +        request.setParameter(FORM_REDIRECT_PARAMETER, redirectUri);
    +        assertEquals(redirectUri, handler.determineTargetUrl(request, new MockHttpServletResponse()));
    +    }
    +
    +    @Test
    +    public void invalidFormRedirectIsNotReturned() {
    +        String redirectUri = "http://test.com/test";
    +
    +        request.setParameter(FORM_REDIRECT_PARAMETER, redirectUri);
    +        assertEquals("/", handler.determineTargetUrl(request, new MockHttpServletResponse()));
    +    }
    +}
    
8a599448781a

Request cache only saves requests with form_redirect_uri if it's valid

https://github.com/cloudfoundry/uaaJaskanwal PawarJun 13, 2018via ghsa
5 files changed · +77 37
  • server/src/main/java/org/cloudfoundry/identity/uaa/util/UaaUrlUtils.java+22 10 modified
    @@ -14,6 +14,15 @@
      */
     package org.cloudfoundry.identity.uaa.util;
     
    +import org.cloudfoundry.identity.uaa.zone.IdentityZone;
    +import org.cloudfoundry.identity.uaa.zone.IdentityZoneHolder;
    +import org.springframework.util.AntPathMatcher;
    +import org.springframework.util.MultiValueMap;
    +import org.springframework.util.StringUtils;
    +import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
    +import org.springframework.web.util.UriComponentsBuilder;
    +import org.springframework.web.util.UriUtils;
    +
     import javax.servlet.http.HttpServletRequest;
     import java.io.UnsupportedEncodingException;
     import java.net.MalformedURLException;
    @@ -25,16 +34,6 @@
     import java.util.Map;
     import java.util.regex.Pattern;
     
    -import org.cloudfoundry.identity.uaa.zone.IdentityZone;
    -import org.cloudfoundry.identity.uaa.zone.IdentityZoneHolder;
    -
    -import org.springframework.util.AntPathMatcher;
    -import org.springframework.util.MultiValueMap;
    -import org.springframework.util.StringUtils;
    -import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
    -import org.springframework.web.util.UriComponentsBuilder;
    -import org.springframework.web.util.UriUtils;
    -
     import static java.util.Collections.emptyList;
     import static java.util.Optional.ofNullable;
     import static org.springframework.util.StringUtils.hasText;
    @@ -228,4 +227,17 @@ public static String getRequestPath(HttpServletRequest request) {
             String path = String.format("%s%s", servletPath, pathInfo);
             return path;
         }
    +
    +    public static boolean uriHasMatchingHost(String uri, String hostname) {
    +        if (uri == null) {
    +            return false;
    +        }
    +
    +        try {
    +            URL url = new URL(uri);
    +            return hostname.equals(url.getHost());
    +        } catch (MalformedURLException e) {
    +            return false;
    +        }
    +    }
     }
    
  • server/src/main/java/org/cloudfoundry/identity/uaa/web/UaaSavedRequestAwareAuthenticationSuccessHandler.java+2 16 modified
    @@ -17,12 +17,11 @@
     
     import org.apache.commons.logging.Log;
     import org.apache.commons.logging.LogFactory;
    +import org.cloudfoundry.identity.uaa.util.UaaUrlUtils;
     import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
     
     import javax.servlet.http.HttpServletRequest;
     import javax.servlet.http.HttpServletResponse;
    -import java.net.MalformedURLException;
    -import java.net.URL;
     
     public class UaaSavedRequestAwareAuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {
         public static final String SAVED_REQUEST_SESSION_ATTRIBUTE = "SPRING_SECURITY_SAVED_REQUEST";
    @@ -40,23 +39,10 @@ public String determineTargetUrl(HttpServletRequest request, HttpServletResponse
             if (redirectAttribute !=null) {
                 logger.debug("Returning redirectAttribute saved URI:"+redirectAttribute);
                 return (String) redirectAttribute;
    -        } else if (isApprovedFormRedirectUri(request, redirectFormParam)) {
    +        } else if (UaaUrlUtils.uriHasMatchingHost(redirectFormParam, request.getServerName())) {
                 return redirectFormParam;
             } else {
                 return super.determineTargetUrl(request, response);
             }
         }
    -
    -    private boolean isApprovedFormRedirectUri(HttpServletRequest request, String redirectUri) {
    -        if (redirectUri == null) {
    -            return false;
    -        }
    -
    -        try {
    -            URL url = new URL(redirectUri);
    -            return request.getServerName().equals(url.getHost());
    -        } catch (MalformedURLException e) {
    -            return false;
    -        }
    -    }
     }
    
  • server/src/main/java/org/cloudfoundry/identity/uaa/web/UaaSavedRequestCache.java+3 1 modified
    @@ -92,7 +92,9 @@ protected boolean shouldSaveFormRedirectParameter(HttpServletRequest request) {
             if (StringUtils.isEmpty(formRedirect)) {
                 return false;
             }
    -
    +        if (!UaaUrlUtils.uriHasMatchingHost(formRedirect, request.getServerName())) {
    +            return false;
    +        }
             if (hasSavedRequest(request)) {
                 return false;
             }
    
  • server/src/test/java/org/cloudfoundry/identity/uaa/util/UaaUrlUtilsTest.java+22 8 modified
    @@ -12,29 +12,30 @@
      *******************************************************************************/
     package org.cloudfoundry.identity.uaa.util;
     
    -import java.util.Arrays;
    -import java.util.Collections;
    -import java.util.LinkedHashMap;
    -import java.util.List;
    -import java.util.Map;
    -import java.util.stream.Collectors;
    -
     import org.cloudfoundry.identity.uaa.zone.IdentityZone;
     import org.cloudfoundry.identity.uaa.zone.IdentityZoneHolder;
     import org.cloudfoundry.identity.uaa.zone.MultitenancyFixture;
    -
     import org.junit.After;
     import org.junit.Before;
     import org.junit.Test;
     import org.springframework.mock.web.MockHttpServletRequest;
     import org.springframework.web.context.request.RequestContextHolder;
     import org.springframework.web.context.request.ServletRequestAttributes;
     
    +import java.util.Arrays;
    +import java.util.Collections;
    +import java.util.LinkedHashMap;
    +import java.util.List;
    +import java.util.Map;
    +import java.util.stream.Collectors;
    +
     import static org.hamcrest.CoreMatchers.is;
     import static org.hamcrest.Matchers.equalTo;
     import static org.junit.Assert.assertEquals;
    +import static org.junit.Assert.assertFalse;
     import static org.junit.Assert.assertNotNull;
     import static org.junit.Assert.assertThat;
    +import static org.junit.Assert.assertTrue;
     import static org.junit.Assert.fail;
     
     public class UaaUrlUtilsTest {
    @@ -422,6 +423,19 @@ public void addSubdomain_handlesUnexpectedDotInSubdomain_currentZone() {
             assertEquals("http://somezone2.localhost:8080", url2);
         }
     
    +    @Test
    +    public void testUriHasMatchingHost() {
    +        assertTrue(UaaUrlUtils.uriHasMatchingHost("http://test.com/test", "test.com"));
    +        assertTrue(UaaUrlUtils.uriHasMatchingHost("http://subdomain.test.com/test", "subdomain.test.com"));
    +        assertTrue(UaaUrlUtils.uriHasMatchingHost("http://1.2.3.4/test", "1.2.3.4"));
    +
    +        assertFalse(UaaUrlUtils.uriHasMatchingHost(null, "test.com"));
    +        assertFalse(UaaUrlUtils.uriHasMatchingHost("http://not-test.com/test", "test.com"));
    +        assertFalse(UaaUrlUtils.uriHasMatchingHost("not-valid-url", "test.com"));
    +        assertFalse(UaaUrlUtils.uriHasMatchingHost("http://1.2.3.4/test", "test.com"));
    +        assertFalse(UaaUrlUtils.uriHasMatchingHost("http://test.com/test", "1.2.3.4"));
    +    }
    +
         private void validateRedirectUri(List<String> urls, boolean result) {
             Map<String, String> failed = getFailedUrls(urls, result);
             if (!failed.isEmpty()) {
    
  • server/src/test/java/org/cloudfoundry/identity/uaa/web/UaaSavedRequestCacheTests.java+28 2 modified
    @@ -28,8 +28,13 @@
     import org.springframework.security.web.savedrequest.SavedRequest;
     
     import javax.servlet.FilterChain;
    +import javax.servlet.ServletException;
     import javax.servlet.ServletResponse;
    +import javax.servlet.http.HttpServletRequest;
     import javax.servlet.http.HttpSession;
    +import java.io.IOException;
    +import java.net.MalformedURLException;
    +import java.net.URL;
     
     import static org.cloudfoundry.identity.uaa.web.UaaSavedRequestAwareAuthenticationSuccessHandler.FORM_REDIRECT_PARAMETER;
     import static org.cloudfoundry.identity.uaa.web.UaaSavedRequestAwareAuthenticationSuccessHandler.SAVED_REQUEST_SESSION_ATTRIBUTE;
    @@ -38,6 +43,7 @@
     import static org.junit.Assert.assertFalse;
     import static org.junit.Assert.assertNotNull;
     import static org.junit.Assert.assertTrue;
    +import static org.mockito.ArgumentMatchers.any;
     import static org.mockito.Matchers.anyObject;
     import static org.mockito.Matchers.anyString;
     import static org.mockito.Mockito.mock;
    @@ -103,6 +109,7 @@ public void filter_saves_when_needed() throws Exception {
             request.setPathInfo("/login.do");
             request.setRequestURI("/login.do");
             request.setParameter(FORM_REDIRECT_PARAMETER, redirectUri);
    +        request.setServerName(new URL(redirectUri).getHost());
             assertTrue(cache.shouldSaveFormRedirectParameter(request));
             ServletResponse response = new MockHttpServletResponse();
     
    @@ -145,8 +152,11 @@ public void saveFormRedirectRequest_GET_Method() throws Exception {
     
         @Test
         public void saveFormRedirectRequest() throws Exception {
    +        String redirectUri = "http://login";
             request.setSession(session);
    -        request.setParameter(FORM_REDIRECT_PARAMETER, "http://login");
    +        request.setParameter(FORM_REDIRECT_PARAMETER, redirectUri);
    +        request.setServerName(new URL(redirectUri).getHost());
    +
             spy.saveRequest(request, new MockHttpServletResponse());
             verify(spy).saveClientRedirect(request, request.getParameter(FORM_REDIRECT_PARAMETER));
         }
    @@ -169,14 +179,19 @@ public void only_save_for_POST_calls() {
         }
     
         @Test
    -    public void should_save_condition_works() {
    +    public void should_save_condition_works() throws MalformedURLException {
             assertFalse(cache.shouldSaveFormRedirectParameter(request));
    +
             request.setPathInfo("/login.do");
             assertFalse(cache.shouldSaveFormRedirectParameter(request));
    +
             request.setParameter(FORM_REDIRECT_PARAMETER, redirectUri);
    +        request.setServerName(new URL(redirectUri).getHost());
             assertTrue(cache.shouldSaveFormRedirectParameter(request));
    +
             request.setSession(session);
             assertTrue(cache.shouldSaveFormRedirectParameter(request));
    +
             ClientRedirectSavedRequest savedRequest = new ClientRedirectSavedRequest(request, redirectUri);
             session.setAttribute(SAVED_REQUEST_SESSION_ATTRIBUTE, savedRequest);
             assertFalse(cache.shouldSaveFormRedirectParameter(request));
    @@ -215,5 +230,16 @@ public void saved_request_matcher() {
     
         }
     
    +    @Test
    +    public void unapprovedFormRedirectRequestDoesNotSave() throws IOException, ServletException {
    +        request.setPathInfo("/login.do");
    +        request.setRequestURI("/login.do");
    +        request.setMethod(HttpMethod.POST.name());
    +        request.setParameter(FORM_REDIRECT_PARAMETER, "http://test.com");
    +        request.setServerName("not-test.com");
    +
    +        spy.doFilter(request, new MockHttpServletResponse(), mock(FilterChain.class));
     
    +        verify(spy, never()).saveClientRedirect(any(HttpServletRequest.class), anyString());
    +    }
     }
    \ No newline at end of file
    
238ce572fdae

Request cache only saves requests with form_redirect_uri if it's valid

https://github.com/cloudfoundry/uaaBruce RicardJun 11, 2018via ghsa
5 files changed · +77 37
  • server/src/main/java/org/cloudfoundry/identity/uaa/util/UaaUrlUtils.java+22 10 modified
    @@ -14,6 +14,15 @@
      */
     package org.cloudfoundry.identity.uaa.util;
     
    +import org.cloudfoundry.identity.uaa.zone.IdentityZone;
    +import org.cloudfoundry.identity.uaa.zone.IdentityZoneHolder;
    +import org.springframework.util.AntPathMatcher;
    +import org.springframework.util.MultiValueMap;
    +import org.springframework.util.StringUtils;
    +import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
    +import org.springframework.web.util.UriComponentsBuilder;
    +import org.springframework.web.util.UriUtils;
    +
     import javax.servlet.http.HttpServletRequest;
     import java.io.UnsupportedEncodingException;
     import java.net.MalformedURLException;
    @@ -25,16 +34,6 @@
     import java.util.Map;
     import java.util.regex.Pattern;
     
    -import org.cloudfoundry.identity.uaa.zone.IdentityZone;
    -import org.cloudfoundry.identity.uaa.zone.IdentityZoneHolder;
    -
    -import org.springframework.util.AntPathMatcher;
    -import org.springframework.util.MultiValueMap;
    -import org.springframework.util.StringUtils;
    -import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
    -import org.springframework.web.util.UriComponentsBuilder;
    -import org.springframework.web.util.UriUtils;
    -
     import static java.util.Collections.emptyList;
     import static java.util.Optional.ofNullable;
     import static org.springframework.util.StringUtils.hasText;
    @@ -228,4 +227,17 @@ public static String getRequestPath(HttpServletRequest request) {
             String path = String.format("%s%s", servletPath, pathInfo);
             return path;
         }
    +
    +    public static boolean uriHasMatchingHost(String uri, String hostname) {
    +        if (uri == null) {
    +            return false;
    +        }
    +
    +        try {
    +            URL url = new URL(uri);
    +            return hostname.equals(url.getHost());
    +        } catch (MalformedURLException e) {
    +            return false;
    +        }
    +    }
     }
    
  • server/src/main/java/org/cloudfoundry/identity/uaa/web/UaaSavedRequestAwareAuthenticationSuccessHandler.java+2 16 modified
    @@ -17,12 +17,11 @@
     
     import org.apache.commons.logging.Log;
     import org.apache.commons.logging.LogFactory;
    +import org.cloudfoundry.identity.uaa.util.UaaUrlUtils;
     import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
     
     import javax.servlet.http.HttpServletRequest;
     import javax.servlet.http.HttpServletResponse;
    -import java.net.MalformedURLException;
    -import java.net.URL;
     
     public class UaaSavedRequestAwareAuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {
         public static final String SAVED_REQUEST_SESSION_ATTRIBUTE = "SPRING_SECURITY_SAVED_REQUEST";
    @@ -40,23 +39,10 @@ public String determineTargetUrl(HttpServletRequest request, HttpServletResponse
             if (redirectAttribute !=null) {
                 logger.debug("Returning redirectAttribute saved URI:"+redirectAttribute);
                 return (String) redirectAttribute;
    -        } else if (isApprovedFormRedirectUri(request, redirectFormParam)) {
    +        } else if (UaaUrlUtils.uriHasMatchingHost(redirectFormParam, request.getServerName())) {
                 return redirectFormParam;
             } else {
                 return super.determineTargetUrl(request, response);
             }
         }
    -
    -    private boolean isApprovedFormRedirectUri(HttpServletRequest request, String redirectUri) {
    -        if (redirectUri == null) {
    -            return false;
    -        }
    -
    -        try {
    -            URL url = new URL(redirectUri);
    -            return request.getServerName().equals(url.getHost());
    -        } catch (MalformedURLException e) {
    -            return false;
    -        }
    -    }
     }
    
  • server/src/main/java/org/cloudfoundry/identity/uaa/web/UaaSavedRequestCache.java+3 1 modified
    @@ -92,7 +92,9 @@ protected boolean shouldSaveFormRedirectParameter(HttpServletRequest request) {
             if (StringUtils.isEmpty(formRedirect)) {
                 return false;
             }
    -
    +        if (!UaaUrlUtils.uriHasMatchingHost(formRedirect, request.getServerName())) {
    +            return false;
    +        }
             if (hasSavedRequest(request)) {
                 return false;
             }
    
  • server/src/test/java/org/cloudfoundry/identity/uaa/util/UaaUrlUtilsTest.java+22 8 modified
    @@ -12,29 +12,30 @@
      *******************************************************************************/
     package org.cloudfoundry.identity.uaa.util;
     
    -import java.util.Arrays;
    -import java.util.Collections;
    -import java.util.LinkedHashMap;
    -import java.util.List;
    -import java.util.Map;
    -import java.util.stream.Collectors;
    -
     import org.cloudfoundry.identity.uaa.zone.IdentityZone;
     import org.cloudfoundry.identity.uaa.zone.IdentityZoneHolder;
     import org.cloudfoundry.identity.uaa.zone.MultitenancyFixture;
    -
     import org.junit.After;
     import org.junit.Before;
     import org.junit.Test;
     import org.springframework.mock.web.MockHttpServletRequest;
     import org.springframework.web.context.request.RequestContextHolder;
     import org.springframework.web.context.request.ServletRequestAttributes;
     
    +import java.util.Arrays;
    +import java.util.Collections;
    +import java.util.LinkedHashMap;
    +import java.util.List;
    +import java.util.Map;
    +import java.util.stream.Collectors;
    +
     import static org.hamcrest.CoreMatchers.is;
     import static org.hamcrest.Matchers.equalTo;
     import static org.junit.Assert.assertEquals;
    +import static org.junit.Assert.assertFalse;
     import static org.junit.Assert.assertNotNull;
     import static org.junit.Assert.assertThat;
    +import static org.junit.Assert.assertTrue;
     import static org.junit.Assert.fail;
     
     public class UaaUrlUtilsTest {
    @@ -422,6 +423,19 @@ public void addSubdomain_handlesUnexpectedDotInSubdomain_currentZone() {
             assertEquals("http://somezone2.localhost:8080", url2);
         }
     
    +    @Test
    +    public void testUriHasMatchingHost() {
    +        assertTrue(UaaUrlUtils.uriHasMatchingHost("http://test.com/test", "test.com"));
    +        assertTrue(UaaUrlUtils.uriHasMatchingHost("http://subdomain.test.com/test", "subdomain.test.com"));
    +        assertTrue(UaaUrlUtils.uriHasMatchingHost("http://1.2.3.4/test", "1.2.3.4"));
    +
    +        assertFalse(UaaUrlUtils.uriHasMatchingHost(null, "test.com"));
    +        assertFalse(UaaUrlUtils.uriHasMatchingHost("http://not-test.com/test", "test.com"));
    +        assertFalse(UaaUrlUtils.uriHasMatchingHost("not-valid-url", "test.com"));
    +        assertFalse(UaaUrlUtils.uriHasMatchingHost("http://1.2.3.4/test", "test.com"));
    +        assertFalse(UaaUrlUtils.uriHasMatchingHost("http://test.com/test", "1.2.3.4"));
    +    }
    +
         private void validateRedirectUri(List<String> urls, boolean result) {
             Map<String, String> failed = getFailedUrls(urls, result);
             if (!failed.isEmpty()) {
    
  • server/src/test/java/org/cloudfoundry/identity/uaa/web/UaaSavedRequestCacheTests.java+28 2 modified
    @@ -28,8 +28,13 @@
     import org.springframework.security.web.savedrequest.SavedRequest;
     
     import javax.servlet.FilterChain;
    +import javax.servlet.ServletException;
     import javax.servlet.ServletResponse;
    +import javax.servlet.http.HttpServletRequest;
     import javax.servlet.http.HttpSession;
    +import java.io.IOException;
    +import java.net.MalformedURLException;
    +import java.net.URL;
     
     import static org.cloudfoundry.identity.uaa.web.UaaSavedRequestAwareAuthenticationSuccessHandler.FORM_REDIRECT_PARAMETER;
     import static org.cloudfoundry.identity.uaa.web.UaaSavedRequestAwareAuthenticationSuccessHandler.SAVED_REQUEST_SESSION_ATTRIBUTE;
    @@ -38,6 +43,7 @@
     import static org.junit.Assert.assertFalse;
     import static org.junit.Assert.assertNotNull;
     import static org.junit.Assert.assertTrue;
    +import static org.mockito.ArgumentMatchers.any;
     import static org.mockito.Matchers.anyObject;
     import static org.mockito.Matchers.anyString;
     import static org.mockito.Mockito.mock;
    @@ -103,6 +109,7 @@ public void filter_saves_when_needed() throws Exception {
             request.setPathInfo("/login.do");
             request.setRequestURI("/login.do");
             request.setParameter(FORM_REDIRECT_PARAMETER, redirectUri);
    +        request.setServerName(new URL(redirectUri).getHost());
             assertTrue(cache.shouldSaveFormRedirectParameter(request));
             ServletResponse response = new MockHttpServletResponse();
     
    @@ -145,8 +152,11 @@ public void saveFormRedirectRequest_GET_Method() throws Exception {
     
         @Test
         public void saveFormRedirectRequest() throws Exception {
    +        String redirectUri = "http://login";
             request.setSession(session);
    -        request.setParameter(FORM_REDIRECT_PARAMETER, "http://login");
    +        request.setParameter(FORM_REDIRECT_PARAMETER, redirectUri);
    +        request.setServerName(new URL(redirectUri).getHost());
    +
             spy.saveRequest(request, new MockHttpServletResponse());
             verify(spy).saveClientRedirect(request, request.getParameter(FORM_REDIRECT_PARAMETER));
         }
    @@ -169,14 +179,19 @@ public void only_save_for_POST_calls() {
         }
     
         @Test
    -    public void should_save_condition_works() {
    +    public void should_save_condition_works() throws MalformedURLException {
             assertFalse(cache.shouldSaveFormRedirectParameter(request));
    +
             request.setPathInfo("/login.do");
             assertFalse(cache.shouldSaveFormRedirectParameter(request));
    +
             request.setParameter(FORM_REDIRECT_PARAMETER, redirectUri);
    +        request.setServerName(new URL(redirectUri).getHost());
             assertTrue(cache.shouldSaveFormRedirectParameter(request));
    +
             request.setSession(session);
             assertTrue(cache.shouldSaveFormRedirectParameter(request));
    +
             ClientRedirectSavedRequest savedRequest = new ClientRedirectSavedRequest(request, redirectUri);
             session.setAttribute(SAVED_REQUEST_SESSION_ATTRIBUTE, savedRequest);
             assertFalse(cache.shouldSaveFormRedirectParameter(request));
    @@ -215,5 +230,16 @@ public void saved_request_matcher() {
     
         }
     
    +    @Test
    +    public void unapprovedFormRedirectRequestDoesNotSave() throws IOException, ServletException {
    +        request.setPathInfo("/login.do");
    +        request.setRequestURI("/login.do");
    +        request.setMethod(HttpMethod.POST.name());
    +        request.setParameter(FORM_REDIRECT_PARAMETER, "http://test.com");
    +        request.setServerName("not-test.com");
    +
    +        spy.doFilter(request, new MockHttpServletResponse(), mock(FilterChain.class));
     
    +        verify(spy, never()).saveClientRedirect(any(HttpServletRequest.class), anyString());
    +    }
     }
    \ No newline at end of file
    
f6362a8f1865

Request cache only saves requests with form_redirect_uri if it's valid

https://github.com/cloudfoundry/uaaBruce RicardJun 11, 2018via ghsa
5 files changed · +77 37
  • server/src/main/java/org/cloudfoundry/identity/uaa/util/UaaUrlUtils.java+22 10 modified
    @@ -14,6 +14,15 @@
      */
     package org.cloudfoundry.identity.uaa.util;
     
    +import org.cloudfoundry.identity.uaa.zone.IdentityZone;
    +import org.cloudfoundry.identity.uaa.zone.IdentityZoneHolder;
    +import org.springframework.util.AntPathMatcher;
    +import org.springframework.util.MultiValueMap;
    +import org.springframework.util.StringUtils;
    +import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
    +import org.springframework.web.util.UriComponentsBuilder;
    +import org.springframework.web.util.UriUtils;
    +
     import javax.servlet.http.HttpServletRequest;
     import java.io.UnsupportedEncodingException;
     import java.net.MalformedURLException;
    @@ -25,16 +34,6 @@
     import java.util.Map;
     import java.util.regex.Pattern;
     
    -import org.cloudfoundry.identity.uaa.zone.IdentityZone;
    -import org.cloudfoundry.identity.uaa.zone.IdentityZoneHolder;
    -
    -import org.springframework.util.AntPathMatcher;
    -import org.springframework.util.MultiValueMap;
    -import org.springframework.util.StringUtils;
    -import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
    -import org.springframework.web.util.UriComponentsBuilder;
    -import org.springframework.web.util.UriUtils;
    -
     import static java.util.Collections.emptyList;
     import static java.util.Optional.ofNullable;
     import static org.springframework.util.StringUtils.hasText;
    @@ -228,4 +227,17 @@ public static String getRequestPath(HttpServletRequest request) {
             String path = String.format("%s%s", servletPath, pathInfo);
             return path;
         }
    +
    +    public static boolean uriHasMatchingHost(String uri, String hostname) {
    +        if (uri == null) {
    +            return false;
    +        }
    +
    +        try {
    +            URL url = new URL(uri);
    +            return hostname.equals(url.getHost());
    +        } catch (MalformedURLException e) {
    +            return false;
    +        }
    +    }
     }
    
  • server/src/main/java/org/cloudfoundry/identity/uaa/web/UaaSavedRequestAwareAuthenticationSuccessHandler.java+2 16 modified
    @@ -17,12 +17,11 @@
     
     import org.apache.commons.logging.Log;
     import org.apache.commons.logging.LogFactory;
    +import org.cloudfoundry.identity.uaa.util.UaaUrlUtils;
     import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
     
     import javax.servlet.http.HttpServletRequest;
     import javax.servlet.http.HttpServletResponse;
    -import java.net.MalformedURLException;
    -import java.net.URL;
     
     public class UaaSavedRequestAwareAuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {
         public static final String SAVED_REQUEST_SESSION_ATTRIBUTE = "SPRING_SECURITY_SAVED_REQUEST";
    @@ -40,23 +39,10 @@ public String determineTargetUrl(HttpServletRequest request, HttpServletResponse
             if (redirectAttribute !=null) {
                 logger.debug("Returning redirectAttribute saved URI:"+redirectAttribute);
                 return (String) redirectAttribute;
    -        } else if (isApprovedFormRedirectUri(request, redirectFormParam)) {
    +        } else if (UaaUrlUtils.uriHasMatchingHost(redirectFormParam, request.getServerName())) {
                 return redirectFormParam;
             } else {
                 return super.determineTargetUrl(request, response);
             }
         }
    -
    -    private boolean isApprovedFormRedirectUri(HttpServletRequest request, String redirectUri) {
    -        if (redirectUri == null) {
    -            return false;
    -        }
    -
    -        try {
    -            URL url = new URL(redirectUri);
    -            return request.getServerName().equals(url.getHost());
    -        } catch (MalformedURLException e) {
    -            return false;
    -        }
    -    }
     }
    
  • server/src/main/java/org/cloudfoundry/identity/uaa/web/UaaSavedRequestCache.java+3 1 modified
    @@ -92,7 +92,9 @@ protected boolean shouldSaveFormRedirectParameter(HttpServletRequest request) {
             if (StringUtils.isEmpty(formRedirect)) {
                 return false;
             }
    -
    +        if (!UaaUrlUtils.uriHasMatchingHost(formRedirect, request.getServerName())) {
    +            return false;
    +        }
             if (hasSavedRequest(request)) {
                 return false;
             }
    
  • server/src/test/java/org/cloudfoundry/identity/uaa/util/UaaUrlUtilsTest.java+22 8 modified
    @@ -12,29 +12,30 @@
      *******************************************************************************/
     package org.cloudfoundry.identity.uaa.util;
     
    -import java.util.Arrays;
    -import java.util.Collections;
    -import java.util.LinkedHashMap;
    -import java.util.List;
    -import java.util.Map;
    -import java.util.stream.Collectors;
    -
     import org.cloudfoundry.identity.uaa.zone.IdentityZone;
     import org.cloudfoundry.identity.uaa.zone.IdentityZoneHolder;
     import org.cloudfoundry.identity.uaa.zone.MultitenancyFixture;
    -
     import org.junit.After;
     import org.junit.Before;
     import org.junit.Test;
     import org.springframework.mock.web.MockHttpServletRequest;
     import org.springframework.web.context.request.RequestContextHolder;
     import org.springframework.web.context.request.ServletRequestAttributes;
     
    +import java.util.Arrays;
    +import java.util.Collections;
    +import java.util.LinkedHashMap;
    +import java.util.List;
    +import java.util.Map;
    +import java.util.stream.Collectors;
    +
     import static org.hamcrest.CoreMatchers.is;
     import static org.hamcrest.Matchers.equalTo;
     import static org.junit.Assert.assertEquals;
    +import static org.junit.Assert.assertFalse;
     import static org.junit.Assert.assertNotNull;
     import static org.junit.Assert.assertThat;
    +import static org.junit.Assert.assertTrue;
     import static org.junit.Assert.fail;
     
     public class UaaUrlUtilsTest {
    @@ -422,6 +423,19 @@ public void addSubdomain_handlesUnexpectedDotInSubdomain_currentZone() {
             assertEquals("http://somezone2.localhost:8080", url2);
         }
     
    +    @Test
    +    public void testUriHasMatchingHost() {
    +        assertTrue(UaaUrlUtils.uriHasMatchingHost("http://test.com/test", "test.com"));
    +        assertTrue(UaaUrlUtils.uriHasMatchingHost("http://subdomain.test.com/test", "subdomain.test.com"));
    +        assertTrue(UaaUrlUtils.uriHasMatchingHost("http://1.2.3.4/test", "1.2.3.4"));
    +
    +        assertFalse(UaaUrlUtils.uriHasMatchingHost(null, "test.com"));
    +        assertFalse(UaaUrlUtils.uriHasMatchingHost("http://not-test.com/test", "test.com"));
    +        assertFalse(UaaUrlUtils.uriHasMatchingHost("not-valid-url", "test.com"));
    +        assertFalse(UaaUrlUtils.uriHasMatchingHost("http://1.2.3.4/test", "test.com"));
    +        assertFalse(UaaUrlUtils.uriHasMatchingHost("http://test.com/test", "1.2.3.4"));
    +    }
    +
         private void validateRedirectUri(List<String> urls, boolean result) {
             Map<String, String> failed = getFailedUrls(urls, result);
             if (!failed.isEmpty()) {
    
  • server/src/test/java/org/cloudfoundry/identity/uaa/web/UaaSavedRequestCacheTests.java+28 2 modified
    @@ -28,8 +28,13 @@
     import org.springframework.security.web.savedrequest.SavedRequest;
     
     import javax.servlet.FilterChain;
    +import javax.servlet.ServletException;
     import javax.servlet.ServletResponse;
    +import javax.servlet.http.HttpServletRequest;
     import javax.servlet.http.HttpSession;
    +import java.io.IOException;
    +import java.net.MalformedURLException;
    +import java.net.URL;
     
     import static org.cloudfoundry.identity.uaa.web.UaaSavedRequestAwareAuthenticationSuccessHandler.FORM_REDIRECT_PARAMETER;
     import static org.cloudfoundry.identity.uaa.web.UaaSavedRequestAwareAuthenticationSuccessHandler.SAVED_REQUEST_SESSION_ATTRIBUTE;
    @@ -38,6 +43,7 @@
     import static org.junit.Assert.assertFalse;
     import static org.junit.Assert.assertNotNull;
     import static org.junit.Assert.assertTrue;
    +import static org.mockito.ArgumentMatchers.any;
     import static org.mockito.Matchers.anyObject;
     import static org.mockito.Matchers.anyString;
     import static org.mockito.Mockito.mock;
    @@ -103,6 +109,7 @@ public void filter_saves_when_needed() throws Exception {
             request.setPathInfo("/login.do");
             request.setRequestURI("/login.do");
             request.setParameter(FORM_REDIRECT_PARAMETER, redirectUri);
    +        request.setServerName(new URL(redirectUri).getHost());
             assertTrue(cache.shouldSaveFormRedirectParameter(request));
             ServletResponse response = new MockHttpServletResponse();
     
    @@ -145,8 +152,11 @@ public void saveFormRedirectRequest_GET_Method() throws Exception {
     
         @Test
         public void saveFormRedirectRequest() throws Exception {
    +        String redirectUri = "http://login";
             request.setSession(session);
    -        request.setParameter(FORM_REDIRECT_PARAMETER, "http://login");
    +        request.setParameter(FORM_REDIRECT_PARAMETER, redirectUri);
    +        request.setServerName(new URL(redirectUri).getHost());
    +
             spy.saveRequest(request, new MockHttpServletResponse());
             verify(spy).saveClientRedirect(request, request.getParameter(FORM_REDIRECT_PARAMETER));
         }
    @@ -169,14 +179,19 @@ public void only_save_for_POST_calls() {
         }
     
         @Test
    -    public void should_save_condition_works() {
    +    public void should_save_condition_works() throws MalformedURLException {
             assertFalse(cache.shouldSaveFormRedirectParameter(request));
    +
             request.setPathInfo("/login.do");
             assertFalse(cache.shouldSaveFormRedirectParameter(request));
    +
             request.setParameter(FORM_REDIRECT_PARAMETER, redirectUri);
    +        request.setServerName(new URL(redirectUri).getHost());
             assertTrue(cache.shouldSaveFormRedirectParameter(request));
    +
             request.setSession(session);
             assertTrue(cache.shouldSaveFormRedirectParameter(request));
    +
             ClientRedirectSavedRequest savedRequest = new ClientRedirectSavedRequest(request, redirectUri);
             session.setAttribute(SAVED_REQUEST_SESSION_ATTRIBUTE, savedRequest);
             assertFalse(cache.shouldSaveFormRedirectParameter(request));
    @@ -215,5 +230,16 @@ public void saved_request_matcher() {
     
         }
     
    +    @Test
    +    public void unapprovedFormRedirectRequestDoesNotSave() throws IOException, ServletException {
    +        request.setPathInfo("/login.do");
    +        request.setRequestURI("/login.do");
    +        request.setMethod(HttpMethod.POST.name());
    +        request.setParameter(FORM_REDIRECT_PARAMETER, "http://test.com");
    +        request.setServerName("not-test.com");
    +
    +        spy.doFilter(request, new MockHttpServletResponse(), mock(FilterChain.class));
     
    +        verify(spy, never()).saveClientRedirect(any(HttpServletRequest.class), anyString());
    +    }
     }
    \ No newline at end of file
    
7a8f157f7e2f

Validate form_redirect_uri parameter against the request host.

https://github.com/cloudfoundry/uaaBruce RicardJun 11, 2018via ghsa
2 files changed · +33 8
  • server/src/main/java/org/cloudfoundry/identity/uaa/web/UaaSavedRequestAwareAuthenticationSuccessHandler.java+16 1 modified
    @@ -21,6 +21,8 @@
     
     import javax.servlet.http.HttpServletRequest;
     import javax.servlet.http.HttpServletResponse;
    +import java.net.MalformedURLException;
    +import java.net.URL;
     
     public class UaaSavedRequestAwareAuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {
         public static final String SAVED_REQUEST_SESSION_ATTRIBUTE = "SPRING_SECURITY_SAVED_REQUEST";
    @@ -38,10 +40,23 @@ public String determineTargetUrl(HttpServletRequest request, HttpServletResponse
             if (redirectAttribute !=null) {
                 logger.debug("Returning redirectAttribute saved URI:"+redirectAttribute);
                 return (String) redirectAttribute;
    -        } else if (redirectFormParam != null) {
    +        } else if (isApprovedFormRedirectUri(request, redirectFormParam)) {
                 return redirectFormParam;
             } else {
                 return super.determineTargetUrl(request, response);
             }
         }
    +
    +    private boolean isApprovedFormRedirectUri(HttpServletRequest request, String redirectUri) {
    +        if (redirectUri == null) {
    +            return false;
    +        }
    +
    +        try {
    +            URL url = new URL(redirectUri);
    +            return request.getServerName().equals(url.getHost());
    +        } catch (MalformedURLException e) {
    +            return false;
    +        }
    +    }
     }
    
  • server/src/test/java/org/cloudfoundry/identity/uaa/web/UaaSavedRequestAwareAuthenticationSuccessHandlerTests.java+17 7 modified
    @@ -41,16 +41,26 @@ public void allow_url_override() {
             assertEquals("http://test.com", handler.determineTargetUrl(request, new MockHttpServletResponse()));
         }
     
    -    @Test
    -    public void form_parameter_works() {
    -        request.setParameter(FORM_REDIRECT_PARAMETER, "http://test.com");
    -        assertEquals("http://test.com", handler.determineTargetUrl(request, new MockHttpServletResponse()));
    -    }
    -
         @Test
         public void form_parameter_is_overridden() {
             request.setParameter(FORM_REDIRECT_PARAMETER, "http://test.com");
             request.setAttribute(URI_OVERRIDE_ATTRIBUTE, "http://override.test.com");
             assertEquals("http://override.test.com", handler.determineTargetUrl(request, new MockHttpServletResponse()));
         }
    -}
    \ No newline at end of file
    +
    +    @Test
    +    public void validFormRedirectIsReturned() {
    +        String redirectUri = request.getScheme() + "://" + request.getServerName() + "/test";
    +
    +        request.setParameter(FORM_REDIRECT_PARAMETER, redirectUri);
    +        assertEquals(redirectUri, handler.determineTargetUrl(request, new MockHttpServletResponse()));
    +    }
    +
    +    @Test
    +    public void invalidFormRedirectIsNotReturned() {
    +        String redirectUri = "http://test.com/test";
    +
    +        request.setParameter(FORM_REDIRECT_PARAMETER, redirectUri);
    +        assertEquals("/", handler.determineTargetUrl(request, new MockHttpServletResponse()));
    +    }
    +}
    
83c8627c2da7

Validate form_redirect_uri parameter against the request host.

https://github.com/cloudfoundry/uaaBruce RicardJun 11, 2018via ghsa
2 files changed · +33 8
  • server/src/main/java/org/cloudfoundry/identity/uaa/web/UaaSavedRequestAwareAuthenticationSuccessHandler.java+16 1 modified
    @@ -21,6 +21,8 @@
     
     import javax.servlet.http.HttpServletRequest;
     import javax.servlet.http.HttpServletResponse;
    +import java.net.MalformedURLException;
    +import java.net.URL;
     
     public class UaaSavedRequestAwareAuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {
         public static final String SAVED_REQUEST_SESSION_ATTRIBUTE = "SPRING_SECURITY_SAVED_REQUEST";
    @@ -38,10 +40,23 @@ public String determineTargetUrl(HttpServletRequest request, HttpServletResponse
             if (redirectAttribute !=null) {
                 logger.debug("Returning redirectAttribute saved URI:"+redirectAttribute);
                 return (String) redirectAttribute;
    -        } else if (redirectFormParam != null) {
    +        } else if (isApprovedFormRedirectUri(request, redirectFormParam)) {
                 return redirectFormParam;
             } else {
                 return super.determineTargetUrl(request, response);
             }
         }
    +
    +    private boolean isApprovedFormRedirectUri(HttpServletRequest request, String redirectUri) {
    +        if (redirectUri == null) {
    +            return false;
    +        }
    +
    +        try {
    +            URL url = new URL(redirectUri);
    +            return request.getServerName().equals(url.getHost());
    +        } catch (MalformedURLException e) {
    +            return false;
    +        }
    +    }
     }
    
  • server/src/test/java/org/cloudfoundry/identity/uaa/web/UaaSavedRequestAwareAuthenticationSuccessHandlerTests.java+17 7 modified
    @@ -41,16 +41,26 @@ public void allow_url_override() {
             assertEquals("http://test.com", handler.determineTargetUrl(request, new MockHttpServletResponse()));
         }
     
    -    @Test
    -    public void form_parameter_works() {
    -        request.setParameter(FORM_REDIRECT_PARAMETER, "http://test.com");
    -        assertEquals("http://test.com", handler.determineTargetUrl(request, new MockHttpServletResponse()));
    -    }
    -
         @Test
         public void form_parameter_is_overridden() {
             request.setParameter(FORM_REDIRECT_PARAMETER, "http://test.com");
             request.setAttribute(URI_OVERRIDE_ATTRIBUTE, "http://override.test.com");
             assertEquals("http://override.test.com", handler.determineTargetUrl(request, new MockHttpServletResponse()));
         }
    -}
    \ No newline at end of file
    +
    +    @Test
    +    public void validFormRedirectIsReturned() {
    +        String redirectUri = request.getScheme() + "://" + request.getServerName() + "/test";
    +
    +        request.setParameter(FORM_REDIRECT_PARAMETER, redirectUri);
    +        assertEquals(redirectUri, handler.determineTargetUrl(request, new MockHttpServletResponse()));
    +    }
    +
    +    @Test
    +    public void invalidFormRedirectIsNotReturned() {
    +        String redirectUri = "http://test.com/test";
    +
    +        request.setParameter(FORM_REDIRECT_PARAMETER, redirectUri);
    +        assertEquals("/", handler.determineTargetUrl(request, new MockHttpServletResponse()));
    +    }
    +}
    

Vulnerability mechanics

Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

12

News mentions

0

No linked articles in our index yet.