Skip to content

createTempJarFile method has a zipslip that causes arbitrary file writes #344

@808Mak1r

Description

@808Mak1r

Describe the bug
A possible Zip Slip vulnerability exists in the code.Zip Slip is a vulnerability that exploits insecure path manipulation, which allows an attacker to achieve arbitrary file writes by constructing a specific zip file and writing the file to an arbitrary path, including a sensitive or system path, when unzipping it.

To Reproduce
In the following code

File output = createTempJarFile(input, jarEntry.getName());
The method createTempJarFile is called in

    static JarFile getNestedJarFile(URL url) throws IOException {
        StringSequence spec = new StringSequence(url.getFile());
        Map<String, JarFile> cache = fileCache.get();
        JarFile jarFile = (cache != null) ? cache.get(spec.toString()) : null;

        if (jarFile != null) {
            return jarFile;
        } else {
            jarFile = getRootJarFileFromUrl(url);
        }

        int separator;
        int index = indexOfRootSpec(spec);
        if (index == -1) {
            return null;
        }
        StringSequence entryName;
        if ((separator = spec.indexOf(SEPARATOR, index)) > 0) {
            entryName = spec.subSequence(index, separator);
        } else {
            entryName = spec.subSequence(index);
        }
        JarEntry jarEntry = jarFile.getJarEntry(entryName.toString());
        if (jarEntry == null) {
            return null;
        }
        try (InputStream input = jarFile.getInputStream(jarEntry)) {
            File output = createTempJarFile(input, jarEntry.getName());
            jarFile = new JarFile(output);
            addToRootFileCache(url.getPath(), jarFile);
        }

        return jarFile;
    }

In the function createTempJarFile

private static File createTempJarFile(InputStream input, String outputName) throws IOException {

    private static File createTempJarFile(InputStream input, String outputName) throws IOException {
        File dir;
        String fName = (new File(outputName)).getName();
        if (fName.length() < outputName.length()) {
            String localDir = outputName.substring(0, outputName.length() - fName.length());
            Path path = Paths.get(TMP_FILE.getPath() + File.separatorChar + localDir);
            dir = Files.createDirectories(path).toFile();
        } else {
            dir = TMP_FILE;
        }
        File f = new File(dir, fName);
        f.deleteOnExit();
        try (FileOutputStream outputStream = new FileOutputStream(f)) {
            copy(input, outputStream);
        }

        return f;
    }

Fix
Fixing this vulnerability requires stricter validation and normalization of the outputName to ensure that it does not contain any malicious path fragments (e.g., ..) . This can be fixed using the following method:

  1. Validate and normalize the path: ensure that the outputName does not contain a sequence of path traversal characters (e.g. ..) .
  2. Handle paths safely: Use safe path splicing methods and avoid splicing strings directly.
...
    // check outputName,make sure it doesn't contain a sequence of path traversal characters
    if (outputName.contains("..")) {
        throw new IOException("Invalid output name: " + outputName);
    }
...
    if (fName.length() < outputName.length()) {
        String localDir = outputName.substring(0, outputName.length() - fName.length());
        Path path = TMP_FILE.toPath().resolve(localDir).normalize(); // Safe handling of paths with resolve and normalize
        if (!path.startsWith(TMP_FILE.toPath())) { // Ensure that the path is not outside the intended directory
            throw new IOException("Invalid output directory: " + path);
        }
        dir = Files.createDirectories(path).toFile();
    } else {
        dir = TMP_FILE;
    }
...

Expected behavior

Version
easeagent-v2.2.8

Configuration

Logs

OS and Hardware

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions