Coordinated Disclosure Timeline

Summary

Partial path traversal allows to break out of expected folder.

Product

Apache Karaf

Tested Version

Latest revision dc8617af34b64b0dac52d7e337bd22dd6e21b60f on Linux

Details

Issue 1: Partial path traversal in FileUtil.java (GHSL-2022-005)

unjar in FileUtil.java validates [1] if the target file path starts with the expected dir [2].

public static void unjar(JarInputStream jis, File dir) //<----------- [2]
    throws IOException
{
...
        File target = new File(dir, je.getName());
        if (!target.getCanonicalPath().startsWith(dir.getCanonicalPath())) { //<----------- [1]
            throw new IOException("JAR resource cannot contain paths with .. characters");
        }
...

getCanonicalPath transforms the path into a canonical form preventing such attack types as .. in path segments. If the result of dir.getCanonicalPath() is not slash terminated it allows for partial path traversal.

Consider "/usr/outnot".startsWith("/usr/out"). The check is bypassed although it is not the out directory. The terminating slash may be removed in various places. On Linux println(new File("/var/")) returns /var, but println(new File("/var", "/")) - /var/, however println(new File("/var", "/").getCanonicalPath()) - /var.

Impact

This issue allows to break out of expected folder.

Issue 2: Partial path traversal in maven plugin (GHSL-2022-006)

extract in RunMojo.java validates [1] if the file path starts with the expected targetDir [2].

private static void extract(ArchiveInputStream is, File targetDir) throws IOException { //<----------- [2]
...
            String name = entry.getName();
            name = name.substring(name.indexOf("/") + 1);
            File file = new File(targetDir, name);
            if (!file.getCanonicalPath().startsWith(targetDir.getCanonicalPath())) { //<----------- [1]
                throw new IOException("Archive cannot contain paths with .. characters");
            }
...

getCanonicalPath transforms the path into a canonical form preventing such attack types as .. in path segments. If the result of targetDir.getCanonicalPath() is not slash terminated it allows for partial path traversal.

Consider "/usr/outnot".startsWith("/usr/out"). The check is bypassed although it is not the out directory. The terminating slash may be removed in various places. On Linux println(new File("/var/")) returns /var, but println(new File("/var", "/")) - /var/, however println(new File("/var", "/").getCanonicalPath()) - /var.

Impact

This issue allows to break out of expected folder.

CVE

Credit

This issue was discovered and reported by GHSL team member @JarLob (Jaroslav Lobačevski).

Contact

You can contact the GHSL team at securitylab@github.com, please include a reference to GHSL-2022-005 or GHSL-2022-006 in any communication regarding this issue.