Prevents unzipping files outside of the target folder

This commit is contained in:
Marcin Grzejszczak
2022-08-16 16:04:02 +02:00
parent 5a075d1f55
commit 6c79bf8042
3 changed files with 28 additions and 5 deletions

View File

@@ -25,6 +25,7 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipInputStream;
import org.springframework.util.StreamUtils;
@@ -65,14 +66,23 @@ public final class ZipCategory {
try (ZipInputStream zipInput = new ZipInputStream(fileInputStream)) {
for (ZipEntry entry = zipInput.getNextEntry(); entry != null; entry = zipInput.getNextEntry()) {
if (!entry.isDirectory()) {
final File file = new File(destination, entry.getName());
if (file.getParentFile() != null) {
file.getParentFile().mkdirs();
final File destinationFile = new File(destination, entry.getName());
/*
* If we see the relative traversal string of ".." we need to make sure
* that the outputdir + name doesn't leave the outputdir.
*/
String zipEntryName = entry.getName();
if (!destinationFile.toPath().normalize().startsWith(destination.toPath())) {
throw new ZipException("The file " + zipEntryName +
" is trying to leave the target output directory of " + destination);
}
try (OutputStream output = Files.newOutputStream(file.toPath())) {
if (destinationFile.getParentFile() != null) {
destinationFile.getParentFile().mkdirs();
}
try (OutputStream output = Files.newOutputStream(destinationFile.toPath())) {
StreamUtils.copy(zipInput, output);
}
unzippedFiles.add(file);
unzippedFiles.add(destinationFile);
}
else {
final File dir = new File(destination, entry.getName());

View File

@@ -36,4 +36,17 @@ class ZipCategorySpec extends Specification {
}?.text?.trim() == 'test'
}
def 'should not allow malicious traversal'() throws Exception {
given:
File zipFile = new File(ZipCategorySpec.classLoader.getResource('zip/zip-malicious-traversal.zip').toURI())
File tempDir = File.createTempDir()
tempDir.deleteOnExit()
when:
use(ZipCategory) {
zipFile.unzipTo(tempDir)
}
then:
Exception e = thrown()
e.getCause().getMessage().contains("is trying to leave the target output directory")
}
}