VYPR
Moderate severityNVD Advisory· Published Feb 20, 2024· Updated Aug 23, 2024

CVE-2024-25609

CVE-2024-25609

Description

HtmlUtil.escapeRedirect in Liferay Portal 7.2.0 through 7.4.3.12, and older unsupported versions, and Liferay DXP 7.4 before update 9, 7.3 service pack 3, 7.2 fix pack 15 through 18, and older unsupported versions can be circumvented by using two forward slashes, which allows remote attackers to redirect users to arbitrary external URLs via the (1) 'redirect parameter (2) FORWARD_URL` parameter, and (3) others parameters that rely on HtmlUtil.escapeRedirect. This vulnerability is the result of an incomplete fix in CVE-2022-28977.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
com.liferay.portal:release.portal.bomMaven
>= 7.2.0, < 7.4.3.13-ga137.4.3.13-ga13
com.liferay.portal:release.dxp.bomMaven
>= 7.2.10.fp15, <= 7.2.10.fp18
com.liferay.portal:release.dxp.bomMaven
>= 7.4.0, < 7.4.13.u97.4.13.u9

Affected products

2

Patches

7
f015ad20bd9e

LPS-144696 Fix test

https://github.com/liferay/liferay-portalarthurchan35Feb 10, 2022via ghsa
1 file changed · +4 3
  • portal-impl/test/unit/com/liferay/portal/util/PortalImplEscapeRedirectTest.java+4 3 modified
    @@ -209,9 +209,10 @@ public void testEscapeRedirectWithRelativeURL() throws Exception {
     			"user/test/~/control_panel/manage/-/select/image,url/",
     			_portalImpl.escapeRedirect(
     				"user/test/~/control_panel/manage/-/select/image,url/"));
    -		Assert.assertEquals("?param1=abc", "?param1=abc");
    -		Assert.assertEquals("#abc", "#abc");
    -		Assert.assertEquals("", "");
    +		Assert.assertEquals(
    +			"?param1=abc", _portalImpl.escapeRedirect("?param1=abc"));
    +		Assert.assertEquals("#abc", _portalImpl.escapeRedirect("#abc"));
    +		Assert.assertEquals("", _portalImpl.escapeRedirect(""));
     
     		// Relative path with protocol
     
    
702a1e358966

LPS-144696 More test

https://github.com/liferay/liferay-portalarthurchan35Feb 10, 2022via ghsa
1 file changed · +5 0
  • portal-impl/test/unit/com/liferay/portal/util/PortalImplEscapeRedirectTest.java+5 0 modified
    @@ -110,6 +110,8 @@ public void testEscapeRedirectWithDomains() throws Exception {
     
     		Assert.assertNull(_portalImpl.escapeRedirect("//www.google.com"));
     		Assert.assertNull(_portalImpl.escapeRedirect("//www.google.com/"));
    +		Assert.assertNull(
    +			_portalImpl.escapeRedirect("//www.google.com//www.google.com"));
     		Assert.assertNull(_portalImpl.escapeRedirect("https:google.com"));
     		Assert.assertNull(_portalImpl.escapeRedirect(":@liferay.com"));
     		Assert.assertNull(_portalImpl.escapeRedirect("http:/web"));
    @@ -207,6 +209,9 @@ public void testEscapeRedirectWithRelativeURL() throws Exception {
     			"user/test/~/control_panel/manage/-/select/image,url/",
     			_portalImpl.escapeRedirect(
     				"user/test/~/control_panel/manage/-/select/image,url/"));
    +		Assert.assertEquals("?param1=abc", "?param1=abc");
    +		Assert.assertEquals("#abc", "#abc");
    +		Assert.assertEquals("", "");
     
     		// Relative path with protocol
     
    
5c9655c941b1

LPS-144696 Centralize relative path tests

https://github.com/liferay/liferay-portalarthurchan35Feb 10, 2022via ghsa
1 file changed · +29 32
  • portal-impl/test/unit/com/liferay/portal/util/PortalImplEscapeRedirectTest.java+29 32 modified
    @@ -75,27 +75,6 @@ public void testEscapeRedirectWithDomains() throws Exception {
     		};
     		_redirectURLSettingsImpl.securityMode = "domain";
     
    -		// Relative path
    -
    -		Assert.assertEquals("/", _portalImpl.escapeRedirect("/"));
    -		Assert.assertEquals(
    -			"/web/guest", _portalImpl.escapeRedirect("/web/guest"));
    -		Assert.assertEquals(
    -			"/a/b;c=d?e=f&g=h#x=y",
    -			_portalImpl.escapeRedirect("/a/b;c=d?e=f&g=h#x=y"));
    -		Assert.assertEquals(
    -			"/web/http:", _portalImpl.escapeRedirect("/web/http:"));
    -		Assert.assertEquals(
    -			"web/http:", _portalImpl.escapeRedirect("web/http:"));
    -		Assert.assertEquals(
    -			"test@google.com", _portalImpl.escapeRedirect("test@google.com"));
    -		Assert.assertNull(_portalImpl.escapeRedirect("///liferay.com"));
    -
    -		// Relative path with protocol
    -
    -		Assert.assertNull(_portalImpl.escapeRedirect("https:/path"));
    -		Assert.assertNull(_portalImpl.escapeRedirect("test:/google.com"));
    -
     		// Allowed domains
     
     		Assert.assertEquals(
    @@ -151,17 +130,6 @@ public void testEscapeRedirectWithIPs() throws Exception {
     
     		try {
     
    -			// Relative path
    -
    -			Assert.assertEquals("/", _portalImpl.escapeRedirect("/"));
    -			Assert.assertEquals(
    -				"/web/guest", _portalImpl.escapeRedirect("/web/guest"));
    -			Assert.assertEquals(
    -				"/a/b;c=d?e=f&g=h#x=y",
    -				_portalImpl.escapeRedirect("/a/b;c=d?e=f&g=h#x=y"));
    -			Assert.assertEquals(
    -				"liferay.com", _portalImpl.escapeRedirect("liferay.com"));
    -
     			// Absolute URL
     
     			Assert.assertEquals(
    @@ -207,6 +175,30 @@ public void testEscapeRedirectWithIPs() throws Exception {
     
     	@Test
     	public void testEscapeRedirectWithRelativeURL() throws Exception {
    +
    +		// Relative path
    +
    +		Assert.assertEquals("/", _portalImpl.escapeRedirect("/"));
    +		Assert.assertEquals(
    +			"/web/guest", _portalImpl.escapeRedirect("/web/guest"));
    +		Assert.assertEquals(
    +			"/a/b;c=d?e=f&g=h#x=y",
    +			_portalImpl.escapeRedirect("/a/b;c=d?e=f&g=h#x=y"));
    +		Assert.assertEquals(
    +			"liferay.com", _portalImpl.escapeRedirect("liferay.com"));
    +		Assert.assertEquals("/", _portalImpl.escapeRedirect("/"));
    +		Assert.assertEquals(
    +			"/web/guest", _portalImpl.escapeRedirect("/web/guest"));
    +		Assert.assertEquals(
    +			"/a/b;c=d?e=f&g=h#x=y",
    +			_portalImpl.escapeRedirect("/a/b;c=d?e=f&g=h#x=y"));
    +		Assert.assertEquals(
    +			"/web/http:", _portalImpl.escapeRedirect("/web/http:"));
    +		Assert.assertEquals(
    +			"web/http:", _portalImpl.escapeRedirect("web/http:"));
    +		Assert.assertEquals(
    +			"test@google.com", _portalImpl.escapeRedirect("test@google.com"));
    +		Assert.assertNull(_portalImpl.escapeRedirect("///liferay.com"));
     		Assert.assertEquals(
     			"user/test/~/control_panel/manage/-/select/image%2Clurl/",
     			_portalImpl.escapeRedirect(
    @@ -215,6 +207,11 @@ public void testEscapeRedirectWithRelativeURL() throws Exception {
     			"user/test/~/control_panel/manage/-/select/image,url/",
     			_portalImpl.escapeRedirect(
     				"user/test/~/control_panel/manage/-/select/image,url/"));
    +
    +		// Relative path with protocol
    +
    +		Assert.assertNull(_portalImpl.escapeRedirect("https:/path"));
    +		Assert.assertNull(_portalImpl.escapeRedirect("test:/google.com"));
     	}
     
     	@Test
    
3c5ee2054b44

LPS-144696 Exclude the 1st type of rel-ref, because we don't want it

https://github.com/liferay/liferay-portalarthurchan35Feb 10, 2022via ghsa
1 file changed · +5 8
  • portal-impl/src/com/liferay/portal/util/PortalImpl.java+5 8 modified
    @@ -950,19 +950,16 @@ public String escapeRedirect(String url) {
     
     		if (!uri.isAbsolute()) {
     
    -			// !uri.isAbsolute() ==
     			// https://datatracker.ietf.org/doc/html/rfc3986#section-4.2
     
    -			return url;
    -		}
    +			if (url.startsWith(StringPool.DOUBLE_SLASH)) {
     
    -		String protocol = uri.getScheme();
    +				// "//" authority path-abempty
     
    -		if (protocol == null) {
    -
    -			// Protocol is required
    +				return null;
    +			}
     
    -			return null;
    +			return url;
     		}
     
     		String domain = uri.getHost();
    
dca931af71a3

LPS-144696 Use Library method

https://github.com/liferay/liferay-portalarthurchan35Feb 10, 2022via ghsa
1 file changed · +5 9
  • portal-impl/src/com/liferay/portal/util/PortalImpl.java+5 9 modified
    @@ -948,16 +948,10 @@ public String escapeRedirect(String url) {
     			return null;
     		}
     
    -		String decodedURL = HttpUtil.decodeURL(url);
    +		if (!uri.isAbsolute()) {
     
    -		String domain = uri.getHost();
    -		String path = uri.getPath();
    -
    -		if ((domain == null) && (path != null) &&
    -			!path.equals(StringPool.BLANK) &&
    -			decodedURL.startsWith(HttpUtil.decodeURL(path))) {
    -
    -			// Relative URL
    +			// !uri.isAbsolute() ==
    +			// https://datatracker.ietf.org/doc/html/rfc3986#section-4.2
     
     			return url;
     		}
    @@ -971,6 +965,8 @@ public String escapeRedirect(String url) {
     			return null;
     		}
     
    +		String domain = uri.getHost();
    +
     		if (Validator.isNull(domain)) {
     
     			// Absolute URL must have a domain
    
66f3ae610c24

LPS-144696 Update test

https://github.com/liferay/liferay-portalIstvan SajtosFeb 3, 2022via ghsa
1 file changed · +1 0
  • portal-impl/test/unit/com/liferay/portal/util/PortalImplEscapeRedirectTest.java+1 0 modified
    @@ -130,6 +130,7 @@ public void testEscapeRedirectWithDomains() throws Exception {
     		// Invalid URLs
     
     		Assert.assertNull(_portalImpl.escapeRedirect("//www.google.com"));
    +		Assert.assertNull(_portalImpl.escapeRedirect("//www.google.com/"));
     		Assert.assertNull(_portalImpl.escapeRedirect("https:google.com"));
     		Assert.assertNull(_portalImpl.escapeRedirect(":@liferay.com"));
     		Assert.assertNull(_portalImpl.escapeRedirect("http:/web"));
    
7aca15e7195a

LPS-144696 Fix relative URL check

https://github.com/liferay/liferay-portalIstvan SajtosFeb 2, 2022via ghsa
1 file changed · +6 4
  • portal-impl/src/com/liferay/portal/util/PortalImpl.java+6 4 modified
    @@ -950,8 +950,12 @@ public String escapeRedirect(String url) {
     
     		String decodedURL = HttpUtil.decodeURL(url);
     
    -		if (Validator.isNotNull(uri.getPath()) &&
    -			decodedURL.startsWith(HttpUtil.decodeURL(uri.getPath()))) {
    +		String domain = uri.getHost();
    +		String path = uri.getPath();
    +
    +		if ((domain == null) && (path != null) &&
    +			!path.equals(StringPool.BLANK) &&
    +			decodedURL.startsWith(HttpUtil.decodeURL(path))) {
     
     			// Relative URL
     
    @@ -967,8 +971,6 @@ public String escapeRedirect(String url) {
     			return null;
     		}
     
    -		String domain = uri.getHost();
    -
     		if (Validator.isNull(domain)) {
     
     			// Absolute URL must have a domain
    

Vulnerability mechanics

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

References

10

News mentions

0

No linked articles in our index yet.