diff --git a/src/SharpCompress/Archives/IArchiveEntryExtensions.cs b/src/SharpCompress/Archives/IArchiveEntryExtensions.cs
index f4f8cb6b..d66669b9 100644
--- a/src/SharpCompress/Archives/IArchiveEntryExtensions.cs
+++ b/src/SharpCompress/Archives/IArchiveEntryExtensions.cs
@@ -48,6 +48,7 @@ namespace SharpCompress.Archives
{
string destinationFileName;
string file = Path.GetFileName(entry.Key);
+ string fullDestinationDirectoryPath = Path.GetFullPath(destinationDirectory);
options = options ?? new ExtractionOptions()
{
@@ -58,19 +59,35 @@ namespace SharpCompress.Archives
if (options.ExtractFullPath)
{
string folder = Path.GetDirectoryName(entry.Key);
- string destdir = Path.Combine(destinationDirectory, folder);
+ string destdir = Path.GetFullPath(
+ Path.Combine(fullDestinationDirectoryPath, folder)
+ );
+
if (!Directory.Exists(destdir))
{
+ if (!destdir.StartsWith(fullDestinationDirectoryPath))
+ {
+ throw new ExtractionException("Entry is trying to create a directory outside of the destination directory.");
+ }
+
Directory.CreateDirectory(destdir);
}
destinationFileName = Path.Combine(destdir, file);
}
else
{
- destinationFileName = Path.Combine(destinationDirectory, file);
+ destinationFileName = Path.Combine(fullDestinationDirectoryPath, file);
}
+
if (!entry.IsDirectory)
{
+ destinationFileName = Path.GetFullPath(destinationFileName);
+
+ if (!destinationFileName.StartsWith(fullDestinationDirectoryPath))
+ {
+ throw new ExtractionException("Entry is trying to write a file outside of the destination directory.");
+ }
+
entry.WriteToFile(destinationFileName, options);
}
}
diff --git a/tests/SharpCompress.Test/SharpCompress.Test.csproj b/tests/SharpCompress.Test/SharpCompress.Test.csproj
index 5635735e..6ae16ea3 100644
--- a/tests/SharpCompress.Test/SharpCompress.Test.csproj
+++ b/tests/SharpCompress.Test/SharpCompress.Test.csproj
@@ -15,5 +15,6 @@
+
\ No newline at end of file
diff --git a/tests/SharpCompress.Test/Zip/ZipArchiveTests.cs b/tests/SharpCompress.Test/Zip/ZipArchiveTests.cs
index a613abad..da17ccbf 100644
--- a/tests/SharpCompress.Test/Zip/ZipArchiveTests.cs
+++ b/tests/SharpCompress.Test/Zip/ZipArchiveTests.cs
@@ -433,7 +433,29 @@ namespace SharpCompress.Test.Zip
}
}
}
+ }
+ [SkippableFact]
+ public void Zip_Evil_Throws_Exception()
+ {
+ //windows only because of the paths
+ Skip.IfNot(Environment.OSVersion.Platform == PlatformID.Win32NT);
+
+ string zipFile = Path.Combine(TEST_ARCHIVES_PATH, "Zip.Evil.zip");
+
+ Assert.ThrowsAny(() => {
+ using (var archive = ZipArchive.Open(zipFile))
+ {
+ foreach (var entry in archive.Entries.Where(entry => !entry.IsDirectory))
+ {
+ entry.WriteToDirectory(SCRATCH_FILES_PATH, new ExtractionOptions()
+ {
+ ExtractFullPath = true,
+ Overwrite = true
+ });
+ }
+ }
+ });
}
class NonSeekableMemoryStream : MemoryStream
diff --git a/tests/TestArchives/Archives/Zip.Evil.zip b/tests/TestArchives/Archives/Zip.Evil.zip
new file mode 100644
index 00000000..3474c88b
Binary files /dev/null and b/tests/TestArchives/Archives/Zip.Evil.zip differ