From PostAuth RCE to PreAuth RCE on Liferay Portal
The post presents a discovery about CVE-2019-16891 that allows exploiting this vulnerability on Liferay Portal without authentication as everyone knows.
About CVE-2019-16891
References
Liferay Portal 7.1.0 and earlier is vulnerable to remote code execution (RCE) via deserialization of JSON data.
According to NVD database, CVE-2019-16891 has a CVSS score of 8.8
because it requires an account on Liferay to exploit successfully.
The root cause
Liferay overridden deserialize
func when implementing JSONFactoryImpl
class from com.liferay.portal.kernel.json.JSONFactory
@Override
public Object deserialize(String json) {
try {
return _jsonSerializer.fromJSON(json);
}
We can see the actual deserialization issue is deeper:
deserialize()
callfromJSON()
fromJSON()
callunmarshall()
: https://github.com/Servoy/jabsorb/blob/master/src/org/jabsorb/JSONSerializer.java#L262So the vulnerability is inside
org.jabsorb.JSONSerializer
library.
Liferay Team was fixed in 2018 by implementing getClassFromHint
to whitelist during deserialization.
Found Second Vulnerable Endpoint
After determining the root cause. I searched the source code for locations using the deserialize
function with the keyword JSONFactoryUtil.deserialize
. A sufficient condition for successful exploiting is that the parameter passed to JSONFactoryUtil.deserialize
is taint from user input.
And this is the location I found: https://github.com/liferay/liferay-portal/blob/6.2.x/portal-impl/src/com/liferay/portal/action/PortletURLAction.java#L167:L172
The endpoint is map to Portlet URL feature (turn off by default) and here is the endpoint that can be successfully called without authentication:
PoC
POST /c/portal/portlet_url HTTP/1.1
Host: liferay.victim.example.com
User-Agent: Mozilla/5.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
X-Requested-With: XMLHttpRequest
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Origin: http://liferay.victim.example.com
Connection: close
Referer: http://liferay.victim.example.com
parameterMap={"Json payload for deserialization in here!"}
Detect vulnerable Liferay Portal instance
GET /c/portal/portlet_url
return 200 status code
Version <= 7.1.0
Conclusion
New CVSS score: 9.8 - Critical (https://nvd.nist.gov/vuln-metrics/cvss/v3-calculator?vector=AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H&version=3.1)
Upgrade Liferay Portal (https://liferay.dev/portal/security/known-vulnerabilities/-/asset_publisher/jekt/content/cst-7111)
Liferay Portal 7.1: There is no patch available for Liferay Portal 7.1.0. Instead, users should upgrade to Liferay Portal 7.1 CE GA2 (7.1.1) or later.
Liferay Portal 7.0: Source patch for Liferay Portal 7.0 GA7 (7.0.6) is available on GitHub. Details for working with source patches can be found on the Patching Liferay Portal page.
Liferay Portal 6.2: Source patch for Liferay Portal 6.2 GA6 (6.2.5) is available on GitHub. Details for working with source patches can be found on the Patching Liferay Portal page.
Update
12/21/2022: NVD rescored CVSS to 9.8 for this vulnerability
12/27/2022: MITRE added my advisory to the References