Skip to content

Commit

Permalink
Merge pull request #1211 from Fedict/issues/#1210-zip-travers
Browse files Browse the repository at this point in the history
Verify that zip file entries don't try to escape the parent dir + test
  • Loading branch information
barthanssens authored Dec 19, 2018
2 parents 0f56f81 + d4464b4 commit b7dae5e
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 1 deletion.
13 changes: 12 additions & 1 deletion util/src/main/java/org/eclipse/rdf4j/common/io/ZipUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,13 @@ public class ZipUtil {
*/
private final static byte MAGIC_NUMBER[] = { (byte)0x50, (byte)0x4B, (byte)0x03, (byte)0x04 };

/**
* Test if an input stream is a zip input stream by checking the "magic number"
*
* @param in input stream
* @return true if start of input stream matches magic number
* @throws IOException
*/
public static boolean isZipStream(InputStream in)
throws IOException
{
Expand Down Expand Up @@ -61,7 +68,7 @@ public static void extract(File zipFile, File destDir)
* @param destDir
* the destination directory
* @throws IOException
* when something untowards happens during the extraction process
* when something untoward happens during the extraction process
*/
public static void extract(ZipFile zipFile, File destDir)
throws IOException
Expand Down Expand Up @@ -92,6 +99,10 @@ public static void writeEntry(ZipFile zipFile, ZipEntry entry, File destDir)
{
File outFile = new File(destDir, entry.getName());

if (! outFile.getCanonicalFile().toPath().startsWith(destDir.getCanonicalFile().toPath())) {
throw new IOException("Zip entry outside destination directory: " + entry.getName());
}

if (entry.isDirectory()) {
outFile.mkdirs();
}
Expand Down
69 changes: 69 additions & 0 deletions util/src/test/java/org/eclipse/rdf4j/common/io/ZipUtilTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*******************************************************************************
* Copyright (c) 2018 Eclipse RDF4J contributors.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Distribution License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*******************************************************************************/
package org.eclipse.rdf4j.common.io;

import static org.junit.Assert.assertEquals;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;

public class ZipUtilTest {
@Rule
public TemporaryFolder dir = new TemporaryFolder();

@Test
public void testWriteEntryNormal() throws IOException {
File f = dir.newFile("testok.zip");

try (ZipOutputStream out = new ZipOutputStream(new FileOutputStream(f))) {
ZipEntry e = new ZipEntry("helloworld.txt");
out.putNextEntry(e);
out.write("hello world".getBytes());
out.closeEntry();
}

ZipFile zf = new ZipFile(f);
File subdir = dir.newFolder("extract");
ZipUtil.extract(zf, subdir);

assertTrue("File not extracted", new File(subdir, "helloworld.txt").exists());
}


@Test
public void testWriteEntryPathTraversing() throws IOException {
File f = dir.newFile("testnotok.zip");

try (ZipOutputStream out = new ZipOutputStream(new FileOutputStream(f))) {
ZipEntry e = new ZipEntry("hello/../../world.txt");
out.putNextEntry(e);
out.write("hello world".getBytes());
out.closeEntry();
}

ZipFile zf = new ZipFile(f);
File subdir = dir.newFolder("extract");
try {
ZipUtil.extract(zf, subdir);
fail("No exception thrown");
} catch (IOException ioe) {
assertTrue(ioe.getMessage().startsWith("Zip entry outside destination directory"));
}
}
}

0 comments on commit b7dae5e

Please # to comment.