*Filed: November 2022 | Author: Security Insights Team*

Liferay Portal powers many business web applications. But from version 7.4.3.5 through 7.4.3.35 (and Liferay DXP 7.4 update 1-34), a critical bug called CVE-2022-42125 left the door wide open for trouble. This bug, known as a Zip Slip vulnerability, made it shockingly easy for attackers to sneak malicious files into your server – just by tricking the system into extracting a bad ZIP file as a plugin or module.

If your company’s web portal runs Liferay and you manage plugin deployment, read on! We’ll explain how attackers could use this flaw, show simple code examples, and share what you should do right now.

What Is a Zip Slip?

Zip Slip is a well-known attack that takes advantage of risky unzip code. If a program doesn’t check the filenames inside a ZIP archive, a ZIP entry can include path traversal sequences (../). When the file is extracted, it isn’t put only into the “safe” folder – it could land anywhere, even overwriting critical system files!

Example

Evil ZIP archive contains this entry:
/tmp/uploads/../../../tomcat/webapps/ROOT/index.jsp

If extracted without checks, the attacker’s JSP file ends up in your website root—ready to run as server code!

Where’s the Flaw in Liferay Portal?

The bug sits in the Liferay code for plugin/module uploads. The method FileUtil.unzip accepts ZIP files when plugins are deployed.

Liferay DXP 7.4 Update 1 – 34

When a user (or attacker) uploads a ZIP file, Liferay fails to check if the filenames are clean. This allows ZIP entries like ../../etc/passwd to be written anywhere on the server where permissions allow.

References

- NIST NVD CVE-2022-42125
- Liferay Security Advisory

Evil ZIP File Structure

evil-plugin.zip
├── ../../../webapps/ROOT/evil.jsp
├── META-INF/MANIFEST.MF

When Liferay’s FileUtil.unzip does this (simplified code!)

try (ZipInputStream zis = new ZipInputStream(new FileInputStream(zipFile))) {
    ZipEntry entry;
    while ((entry = zis.getNextEntry()) != null) {
        File outFile = new File(outputDirectory, entry.getName());
        try (FileOutputStream fos = new FileOutputStream(outFile)) {
            // ...copy file data...
        }
    }
}

The attacker’s path, with ../../../, escapes the target folder, letting them write anywhere!

Proof-of-Concept (PoC) Sample

Here’s a Python snippet for crafting a malicious ZIP that overwrites “out.txt” in the system’s root directory:

import zipfile

with zipfile.ZipFile('evil.zip', 'w') as z:
    # Escape out of the extraction directory
    z.writestr('../../out.txt', 'HACKED by Zip Slip!')
print("evil.zip ready to deploy!")

If you upload this as a plugin on a vulnerable server, “/out.txt” will be overwritten or created!

An attacker could

- Overwrite deployed application code (e.g., drop a webshell in /webapps/ROOT/evil.jsp)

Escalate privileges or gain remote code execution

Attackers only need the ability to upload a plugin or module, either via admin credentials or a compromised account.

The fix is to sanitize ZIP entries before extraction. Here’s the *safe* way (pseudo-Java)

String outPath = Paths.get(outputDir, entry.getName()).normalize().toString();
if (!outPath.startsWith(Paths.get(outputDir).toString())) {
    // Alert! Entry is trying to escape
    throw new SecurityException("Zip Slip detected: " + entry.getName());
}

Upgrade immediately to Liferay 7.4.3.36 (or higher) or DXP 7.4 Update 35+

- Disable plugin/module uploads from untrusted sources

Monitor for suspicious files in unexpected directories

Bonus: Scan your own code for similar ZIP extraction issues elsewhere!

More Reading

- Liferay’s Official Fix Announcement
- Snyk Zip Slip Deep Dive
- OWASP Path Traversal

In Closing

The CVE-2022-42125 teaches a timeless lesson: never trust user-supplied ZIP files! One naive unzip can undo all your other security.

Got questions? Concerned your portal was exploited? Share with your security team and make your developers aware—before something slips through.

Timeline

Published on: 11/15/2022 01:15:00 UTC
Last modified on: 11/18/2022 16:51:00 UTC