CVE-2022-4493: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal') (CWE-22)
value: A vulnerability classified as critical was found in scifio. Affected by this vulnerability is the function downloadAndUnpackResource of the file src/test/java/io/scif/util/DefaultSampleFilesService.java of the component ZIP File Handler. The manipulation leads to path traversal. The attack can be launched remotely. The name of the patch is fcb0dbca0ec72b22fe0c9ddc8abc9cb188a0ff31. It is recommended to apply a patch to fix this issue. The associated identifier of this vulnerability is VDB-215803.
CWE description: The product uses external input to construct a pathname that is intended to identify a file or directory that is located underneath a restricted parent directory, but the product does not properly neutralize special elements within the pathname that can cause the pathname to resolve to a location that is outside of the restricted directory.
CVSS v3 base score: 9.8
Published: 2022-12-14T12:15Z
Repository: https://github.com/scifio/scifio
Language: Java
Files changed: src/test/java/io/scif/util/DefaultSampleFilesService.java
Commit date: 2022-07-30 01:41:08 +0000
Commit message: vuln-fix: Zip Slip Vulnerability

This fixes a Zip-Slip vulnerability.

This change does one of two things. This change either

1. Inserts a guard to protect against Zip Slip.
OR
2. Replaces `dir.getCanonicalPath().startsWith(parent.getCanonicalPath())`, which is vulnerable to partial path traversal attacks, with the more secure `dir.getCanonicalFile().toPath().startsWith(parent.getCanonicalFile().toPath())`.

For number 2, consider `"/usr/outnot".startsWith("/usr/out")`.
The check is bypassed although `/outnot` is not under the `/out` directory.
It's important to understand that the terminating slash may be removed when using various `String` representations of the `File` object.
For example, on Linux, `println(new File("/var"))` will print `/var`, but `println(new File("/var", "/")` will print `/var/`;
however, `println(new File("/var", "/").getCanonicalPath())` will print `/var`.

Weakness: CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')
Severity: High
CVSSS: 7.4
Detection: CodeQL (https://codeql.github.com/codeql-query-help/java/java-zipslip/) & OpenRewrite (https://public.moderne.io/recipes/org.openrewrite.java.security.ZipSlip)

Reported-by: Jonathan Leitschuh <Jonathan.Leitschuh@gmail.com>
Signed-off-by: Jonathan Leitschuh <Jonathan.Leitschuh@gmail.com>

Bug-tracker: https://github.com/JLLeitschuh/security-research/issues/16

Co-authored-by: Moderne <team@moderne.io>
Diff: diff --git a/src/test/java/io/scif/util/DefaultSampleFilesService.java b/src/test/java/io/scif/util/DefaultSampleFilesService.java
index b9e9f437e..548a47018 100644
--- a/src/test/java/io/scif/util/DefaultSampleFilesService.java
+++ b/src/test/java/io/scif/util/DefaultSampleFilesService.java
@@ -157,10 +157,13 @@ public class DefaultSampleFilesService extends AbstractService implements
 			while (true) {
 				final ZipEntry entry = zis.getNextEntry();
 				if (entry == null) break; // All done!
 				final String name = entry.getName();
 				final File outFile = new File(targetFolder, name);
+				if (!outFile.toPath().normalize().startsWith(targetFolder.toPath().normalize())) {
+					throw new RuntimeException("Bad zip entry");
+				}
 				if (entry.isDirectory()) {
 					outFile.mkdirs();
 				}
 				else {
 					final int size = (int) entry.getSize();

Fixed code: 				if (!outFile.toPath().normalize().startsWith(targetFolder.toPath().normalize())) {
					throw new RuntimeException("Bad zip entry");
				}