VYPR
High severityNVD Advisory· Published Aug 3, 2021· Updated Aug 3, 2024

CVE-2021-33322

CVE-2021-33322

Description

In Liferay Portal 7.3.0 and earlier, and Liferay DXP 7.0 before fix pack 96, 7.1 before fix pack 18, and 7.2 before fix pack 5, password reset tokens are not invalidated after a user changes their password, which allows remote attackers to change the user’s password via the old password reset token.

AI Insight

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

Liferay Portal and DXP fail to invalidate password reset tokens after password change, allowing attackers to reuse an old token to reset the user's password.

Vulnerability

In Liferay Portal 7.3.0 and earlier, and Liferay DXP 7.0 before fix pack 96, 7.1 before fix pack 18, and 7.2 before fix pack 5, a flaw in the password reset flow leaves password reset tokens valid even after a user successfully changes their password. The _invalidateTicket method was not called in the updatePassword and updatePasswordManually functions prior to the fix [3][4]. This means an issued reset token remains active indefinitely, rather than being invalidated upon password change. The issue affects the ticket management system that handles password reset tokens [1].

Exploitation

An attacker who has obtained a valid password reset token (for example, through intercepting a password reset email, or by having prior access to the token via another vulnerability) can use that token to change the victim's password even after the legitimate user has already changed their password. No additional authentication is required once the attacker holds the token. The attacker only needs network access to the Liferay instance's password reset endpoint [1]. The attack sequence involves: obtaining the old reset token, sending a password reset request with that token, and setting a new password of the attacker's choosing.

Impact

Successful exploitation allows a remote attacker to arbitrarily change a user's password without knowing the current password. This results in a complete compromise of the victim's account, leading to unauthorized access to all data and functionality associated with that user within the Liferay portal. The impact is particularly severe for administrative accounts, as the attacker could gain elevated privileges [1].

Mitigation

Liferay released fixes for this vulnerability in Liferay DXP 7.0 fix pack 96, 7.1 fix pack 18, 7.2 fix pack 5, and Liferay Portal 7.3.1. The fix adds calls to _invalidateTicket within the updatePassword and updatePasswordManually methods to ensure all existing password reset tickets are expired when a password is changed [3][4]. Users should upgrade to the patched versions immediately. If upgrading is not possible, restricting network access to the password reset functionality and monitoring for suspicious password reset activity may reduce risk, but a full mitigation requires applying the patch.

AI Insight generated on May 21, 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
com.liferay.portal:com.liferay.portal.implMaven
< 5.7.35.7.3
com.liferay.portal:release.dxp.bomMaven
>= 7.0.0, < 7.0.10.fp967.0.10.fp96
com.liferay.portal:release.dxp.bomMaven
>= 7.1.0, < 7.1.10.fp187.1.10.fp18
com.liferay.portal:release.dxp.bomMaven
>= 7.2.0, < 7.2.10.fp57.2.10.fp5

Affected products

3

Patches

2
9fe453b34f58

LPS-108642 SF simplify

https://github.com/liferay/liferay-portalCarlos Sierra AndrésMar 13, 2020via ghsa
1 file changed · +8 10
  • portal-impl/src/com/liferay/portal/service/impl/UserLocalServiceImpl.java+8 10 modified
    @@ -4808,7 +4808,7 @@ public User updatePassword(
     				null, ServiceContextThreadLocal.getServiceContext());
     		}
     
    -		_invalidateTicket(user.getCompanyId(), User.class.getName(), userId);
    +		_invalidateTicket(user);
     
     		return user;
     	}
    @@ -4843,7 +4843,7 @@ public User updatePasswordManually(
     
     		user = userPersistence.update(user);
     
    -		_invalidateTicket(user.getCompanyId(), User.class.getName(), userId);
    +		_invalidateTicket(user);
     
     		return user;
     	}
    @@ -6896,19 +6896,17 @@ private String _getLocalizedValue(
     		return localizedValueMap.get(fallbackLocale);
     	}
     
    -	private void _invalidateTicket(
    -			long companyId, String className, long classPK)
    -		throws PortalException {
    -
    +	private void _invalidateTicket(User user) throws PortalException {
     		List<Ticket> tickets = ticketLocalService.getTickets(
    -			companyId, className, classPK, TicketConstants.TYPE_PASSWORD);
    +			user.getCompanyId(), User.class.getName(), user.getUserId(),
    +			TicketConstants.TYPE_PASSWORD);
     
     		for (Ticket ticket : tickets) {
     			if (!ticket.isExpired()) {
     				ticketLocalService.updateTicket(
    -					ticket.getTicketId(), className, classPK,
    -					TicketConstants.TYPE_PASSWORD, ticket.getExtraInfo(),
    -					new Date());
    +					ticket.getTicketId(), User.class.getName(),
    +					user.getUserId(), TicketConstants.TYPE_PASSWORD,
    +					ticket.getExtraInfo(), new Date());
     			}
     		}
     	}
    
8f072ee8527a

LPS-108642 Once change the password, we need to invalidate the password reset link

1 file changed · +24 1
  • portal-impl/src/com/liferay/portal/service/impl/UserLocalServiceImpl.java+24 1 modified
    @@ -4808,6 +4808,8 @@ public User updatePassword(
     				null, ServiceContextThreadLocal.getServiceContext());
     		}
     
    +		_invalidateTicket(user.getCompanyId(), User.class.getName(), userId);
    +
     		return user;
     	}
     
    @@ -4839,7 +4841,11 @@ public User updatePasswordManually(
     		user.setPasswordModifiedDate(passwordModifiedDate);
     		user.setDigest(user.getDigest(password));
     
    -		return userPersistence.update(user);
    +		user = userPersistence.update(user);
    +
    +		_invalidateTicket(user.getCompanyId(), User.class.getName(), userId);
    +
    +		return user;
     	}
     
     	/**
    @@ -6890,6 +6896,23 @@ private String _getLocalizedValue(
     		return localizedValueMap.get(fallbackLocale);
     	}
     
    +	private void _invalidateTicket(
    +			long companyId, String className, long classPK)
    +		throws PortalException {
    +
    +		List<Ticket> tickets = ticketLocalService.getTickets(
    +			companyId, className, classPK, TicketConstants.TYPE_PASSWORD);
    +
    +		for (Ticket ticket : tickets) {
    +			if (!ticket.isExpired()) {
    +				ticketLocalService.updateTicket(
    +					ticket.getTicketId(), className, classPK,
    +					TicketConstants.TYPE_PASSWORD, ticket.getExtraInfo(),
    +					new Date());
    +			}
    +		}
    +	}
    +
     	private void _sendNotificationEmail(
     			String fromAddress, String fromName, String toAddress, User toUser,
     			String subject, String body,
    

Vulnerability mechanics

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

References

8

News mentions

0

No linked articles in our index yet.