-
Notifications
You must be signed in to change notification settings - Fork 233
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
CON-626: Fix zip extraction vulnerability when installing plugins (#339)
* add unit test that reproduces the bug * move ZipFiles util to concourse-server project * add better impls in ZipFiles * update method usage in PluginManager * fix formatting * update changelog
- Loading branch information
Showing
10 changed files
with
380 additions
and
161 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
160 changes: 0 additions & 160 deletions
160
concourse-driver-java/src/main/java/com/cinchapi/concourse/util/ZipFiles.java
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
90 changes: 90 additions & 0 deletions
90
concourse-server/src/main/java/com/cinchapi/concourse/util/ZipFiles.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
/* | ||
* Copyright (c) 2013-2018 Cinchapi Inc. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package com.cinchapi.concourse.util; | ||
|
||
import java.io.File; | ||
import java.nio.ByteBuffer; | ||
|
||
import org.zeroturnaround.zip.ZipUtil; | ||
|
||
import com.cinchapi.common.base.Verify; | ||
import com.cinchapi.common.io.ByteBuffers; | ||
|
||
/** | ||
* A utility class for handling zip files | ||
* | ||
* @author Jeff Nelson | ||
*/ | ||
public final class ZipFiles { | ||
|
||
static { | ||
Logging.disable(ZipUtil.class); | ||
} | ||
|
||
/** | ||
* Get the content for the entry at {@code relativeEntryPath} from within | ||
* the zip file. | ||
* | ||
* @param zipPath the path to the zip file | ||
* @param relativeEntryPath the path of the entry to extract | ||
* @return the content of the entry as a {@link ByteBuffer} | ||
*/ | ||
public static ByteBuffer getEntryContent(String zipFile, | ||
String relativeEntryPath) { | ||
return ByteBuffer.wrap( | ||
ZipUtil.unpackEntry(new File(zipFile), relativeEntryPath)); | ||
} | ||
|
||
/** | ||
* Get the content for the entry at {@code relativeEntryPath} from within | ||
* the zip file as a UTF-8 string. | ||
* | ||
* @param zipPath the path to the zip file | ||
* @param relativeEntryPath the path of the entry to extract | ||
* @return the content of the entry as a UTF-8 string | ||
*/ | ||
public static String getEntryContentUtf8(String zipFile, | ||
String relativeEntryPath) { | ||
return ByteBuffers | ||
.getUtf8String(getEntryContent(zipFile, relativeEntryPath)); | ||
} | ||
|
||
/** | ||
* Unzip the contents of the file at {@code zipPath} to the | ||
* {@code destination} directory. | ||
* | ||
* @param zipPath the absolute path to the zip file | ||
* @param destination the absolute path to the destination | ||
*/ | ||
public static void unzip(String zipPath, String destination) { | ||
File dest = new File(destination); | ||
if(!dest.exists()) { | ||
dest.mkdirs(); | ||
} | ||
Verify.thatArgument(dest.isDirectory(), | ||
"Unzip destination must be a directory"); | ||
try { | ||
ZipUtil.unpack(new File(zipPath), dest); | ||
} | ||
catch (org.zeroturnaround.zip.ZipException e) { | ||
IllegalArgumentException ex = new IllegalArgumentException( | ||
e.getMessage()); | ||
ex.setStackTrace(e.getStackTrace()); | ||
throw ex; | ||
} | ||
} | ||
|
||
} |
69 changes: 69 additions & 0 deletions
69
concourse-server/src/test/java/com/cinchapi/concourse/util/ZipFilesTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
/* | ||
* Copyright (c) 2013-2018 Cinchapi Inc. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package com.cinchapi.concourse.util; | ||
|
||
import java.io.IOException; | ||
import java.nio.file.Files; | ||
import java.nio.file.Paths; | ||
|
||
import org.junit.Assert; | ||
import org.junit.Test; | ||
|
||
/** | ||
* Unit tests for the {@link ZipFiles} utility class. | ||
* | ||
* @author Jeff Nelson | ||
*/ | ||
public class ZipFilesTest { | ||
|
||
@Test(expected = IllegalArgumentException.class) | ||
public void testCannotExtractZipContainingEntryWithPathTraversalCharacters() | ||
throws IOException { // CON-626 | ||
String zip = Resources.getAbsolutePath("/evil.zip"); | ||
String parent = FileOps.tempDir("zip"); | ||
String dest = Paths.get(parent).resolve("target").toAbsolutePath() | ||
.toString(); | ||
ZipFiles.unzip(zip, dest); | ||
Assert.assertEquals(1, Files.list(Paths.get(dest)).count()); | ||
Assert.assertEquals(1, Files.list(Paths.get(parent)).count()); | ||
} | ||
|
||
@Test(expected = IllegalArgumentException.class) | ||
public void testCannotExtractZipFileToNonDestination() { | ||
String zip = Resources.getAbsolutePath("/good.zip"); | ||
String dest = FileOps.tempFile(); | ||
ZipFiles.unzip(zip, dest); | ||
} | ||
|
||
@Test | ||
public void testGetEntryContentUtf8() { | ||
String zip = Resources.getAbsolutePath("/good.zip"); | ||
String content = ZipFiles.getEntryContentUtf8(zip, "file.txt"); | ||
Assert.assertEquals("Hello World", content); | ||
} | ||
|
||
@Test | ||
public void testUnzip() throws IOException { | ||
String zip = Resources.getAbsolutePath("/good.zip"); | ||
String parent = FileOps.tempDir("zip"); | ||
String dest = Paths.get(parent).resolve("target").toAbsolutePath() | ||
.toString(); | ||
ZipFiles.unzip(zip, dest); | ||
Assert.assertEquals(1, Files.list(Paths.get(dest)).count()); | ||
Assert.assertEquals(1, Files.list(Paths.get(parent)).count()); | ||
} | ||
|
||
} |
Binary file not shown.
Binary file not shown.
Oops, something went wrong.