Open Source and cloud security monitoring company Snyk has disclosed Zip Slip, an arbitrary file overwrite vulnerability exploited using a specially crafted ZIP archive that holds path traversal filenames. The vulnerability affects thousands of projects including AWS Toolkit for Eclipse, Spring Integration, LinkedIn's Pinot OLAP database, Apache/Twitter Heron, Alibaba JStorm, Jenkins, and Gradle. Issues have also been found amongst other cloud providers and InfoQ will update the post as more information becomes public.
According to the vendor, Java's lack of a central library containing high-level processing of archive files means that the Java ecosystem is particularly vulnerable, with affected Java libraries including Java java.util.zip. Apache commons-compres, Apache Ant, ZeroTurnaround zt-zip and zip4j. Guy Podjarny, CEO of Snyk, also told InfoQ that given that the vulnerability affects any archive format that is supported by the uncompress library and allows relative folders, JAR/EAR/WAR are potentially vulnerable.
A file traversal attack aims to access files and directories that are stored outside the root folder. By manipulating variables that reference files with a "dot-dot-slash (../)" sequence and its variations, or by using absolute file paths, a hacker may be able to access arbitrary files and directories stored on a file system including application source code or configuration and critical system files. For example if a ZIP archive were to contain a file called "../../file.exe", it would break out of the target folder when extracted. This could happen on either the server side or client side and could lead to malicious files being written, or sensitive files overwritten. If an executable or a configuration file is overwritten with a file containing malicious code, the problem can turn into an arbitrary code execution issue.
The following code, from the Snyk white paper, provides an example of vulnerable code snippet in Java:
Enumeration entries=zip.getEntries();
while(entries.hasMoreElements()){
ZipEntry e = entries.nextElement();
File f = new File(dir, e.getName());
InputStream input = zip.getInputStream(e);
IOUtils.copy(input, write(f));
}
Here e.getName() is concatenated with the target directory dir, without any validation, to define the location of the Java File, f. If the filename contains a path that traverses up a directory (i.e. it starts with ../../), then it will be written outside of the target directory by the IOUtils.copy command.
Guarding against the vulnerability is straightforward once you know the exploit is possible; since there is no particular reason why a ZIP archive should need to write a file outside the target directory you can simply check for this and prevent it:
String canonicalDirPath=dir.getCanonicalPath();
String canonicalDestPath=e.getName().getCanonicalPath();
if(!canonicalDestPath.startsWith(canonicalDirPath)){
throw new ArchiverException("Entry is outside of the target dir: "
+ e.getName());
}
Simon Maple, director of developer relations at Snyk, told InfoQ that most vendors they have contacted have fixed the issue within a few days of being contacted.
Java isn't the only language affected but it is the most vulnerable. JavaScript has benefitted from its libraries being more centralised, and both vulnerable libraries that provide the functionality to extract from archives have now been fixed. The .NET ecosystem also has more centralised libraries that perform the extraction functionality and two of these three libraries have already been fixed. The vulnerability is found in NuGet DotNetZip and SharpCompress. In the Go ecosystem mholt archiver has the vulnerability but it has also been fixed. Snyk's research team have not found the bug in either Ruby or Python.
The Snyk GitHub repository that will be kept up to date collaboratively by Snyk and various community project maintainers, containing the full list of the latest vulnerability information around language ecosystems.