Skip to content

Commit

Permalink
Eliminate Zip-Slip vulnernability
Browse files Browse the repository at this point in the history
  • Loading branch information
chanseokoh committed Aug 30, 2018
1 parent 664e546 commit 5d3d2bc
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import com.google.common.io.ByteStreams;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
Expand All @@ -37,13 +38,19 @@ public class ZipUtil {
* @throws IOException when I/O error occurs
*/
public static void unzip(Path archive, Path destination) throws IOException {
String canonicalDestination = destination.toFile().getCanonicalPath();

try (InputStream fileIn = Files.newInputStream(archive);
ZipInputStream zipIn = new ZipInputStream(new BufferedInputStream(fileIn))) {

for (ZipEntry entry = zipIn.getNextEntry(); entry != null; entry = zipIn.getNextEntry()) {
// TODO: check Zip-Slip vulnerability: https://snyk.io/research/zip-slip-vulnerability#java
Path entryPath = destination.resolve(entry.getName());

String canonicalTarget = entryPath.toFile().getCanonicalPath();
if (!canonicalTarget.startsWith(canonicalDestination + File.separator)) {
throw new IOException("Blocked unzipping files outside destination: " + entry.getName());
}

if (entry.isDirectory()) {
Files.createDirectories(entryPath);
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import org.hamcrest.CoreMatchers;
import org.junit.Assert;
import org.junit.Assume;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
Expand All @@ -45,6 +47,22 @@ public void testUnzip_nonExistingDestination() throws URISyntaxException, IOExce
Assert.assertTrue(Files.exists(destination));
}

@Test
public void testZipSlipVulnerability_windows() throws URISyntaxException {
Assume.assumeTrue(System.getProperty("os.name").startsWith("Windows"));

Path archive = Paths.get(Resources.getResource("test-archives/zip-slip-win.zip").toURI());
verifyZipSlipSafe(archive);
}

@Test
public void testZipSlipVulnerability_unix() throws URISyntaxException {
Assume.assumeFalse(System.getProperty("os.name").startsWith("Windows"));

Path archive = Paths.get(Resources.getResource("test-archives/zip-slip.zip").toURI());
verifyZipSlipSafe(archive);
}

private void verifyUnzip(Path destination) throws URISyntaxException, IOException {
Path archive = Paths.get(Resources.getResource("test-archives/test.zip").toURI());

Expand All @@ -59,4 +77,15 @@ private void verifyUnzip(Path destination) throws URISyntaxException, IOExceptio
Assert.assertEquals("file2", Files.readAllLines(file2).get(0));
Assert.assertEquals("file3", Files.readAllLines(file3).get(0));
}

private void verifyZipSlipSafe(Path archive) {
try {
ZipUtil.unzip(archive, tempFolder.getRoot().toPath());
Assert.fail("Should block Zip-Slip");
} catch (IOException ex) {
Assert.assertThat(
ex.getMessage(),
CoreMatchers.startsWith("Blocked unzipping files outside destination: "));
}
}
}
Binary file not shown.
Binary file not shown.

0 comments on commit 5d3d2bc

Please sign in to comment.