This is an automated email from the ASF dual-hosted git repository.

gilbert pushed a commit to branch 1.7.x
in repository https://gitbox.apache.org/repos/asf/mesos.git

commit 9ecbba375e333fe7bfc326e5f9686b6af47a6fbd
Author: Joseph Wu <[email protected]>
AuthorDate: Thu Mar 7 14:39:53 2019 -0800

    Added ARCHIVE_EXTRACT_SECURE_NODOTDOT flag to archiver default.
    
    This enables a security flag provided by libarchive, which disallows
    extraction of archives that contain '..' in hardlinks or files.
    Without this flag, it is possible to provide the archiver with
    an archive and overwrite arbitrary files in the user's parent directory
    or further up.
    
    Review: https://reviews.apache.org/r/70142/
    (cherry picked from commit 792f01f37be73975b444b08df5a93b4d788e007a)
---
 3rdparty/stout/include/stout/archiver.hpp |  2 +-
 3rdparty/stout/tests/archiver_tests.cpp   | 35 +++++++++++++++++++++++++++++++
 2 files changed, 36 insertions(+), 1 deletion(-)

diff --git a/3rdparty/stout/include/stout/archiver.hpp 
b/3rdparty/stout/include/stout/archiver.hpp
index 2447797..551e644 100644
--- a/3rdparty/stout/include/stout/archiver.hpp
+++ b/3rdparty/stout/include/stout/archiver.hpp
@@ -40,7 +40,7 @@ namespace archiver {
 inline Try<Nothing> extract(
   const std::string& source,
   const std::string& destination,
-  const int flags = ARCHIVE_EXTRACT_TIME)
+  const int flags = ARCHIVE_EXTRACT_TIME | ARCHIVE_EXTRACT_SECURE_NODOTDOT)
 {
   // Get references to libarchive for reading/handling a compressed file.
   std::unique_ptr<struct archive, std::function<void(struct archive*)>> reader(
diff --git a/3rdparty/stout/tests/archiver_tests.cpp 
b/3rdparty/stout/tests/archiver_tests.cpp
index cdf24a5..fc0b957 100644
--- a/3rdparty/stout/tests/archiver_tests.cpp
+++ b/3rdparty/stout/tests/archiver_tests.cpp
@@ -537,3 +537,38 @@ TEST_F(ArchiverTest, ExtractZipFileWithLongDestinationDir)
 
   ASSERT_SOME_EQ("Howdy there, partner! (.zip)\n", os::read(extractedFile));
 }
+
+
+TEST_F(ArchiverTest, ExtractZipWithDotDot)
+{
+  // Construct a exploit.zip file that should not be extracted.
+  string dir = path::join(sandbox.get(), "somedir");
+  ASSERT_SOME(os::mkdir(dir));
+
+  Try<string> path = os::mktemp(path::join(dir, "XXXXXX"));
+  ASSERT_SOME(path);
+
+  // Extract from the same directory as the zip file.
+  ASSERT_SOME(os::chdir(dir));
+
+  // This is a file contructed with the following Python code:
+  //   import zipfile
+  //   zip = zipfile.ZipFile("exploit.zip", "w")
+  //   zip.writestr("../unsecure_file.txt", "content")
+  //   zip.close()
+
+  ASSERT_SOME(os::write(path.get(), base64::decode(
+      "UEsDBBQAAAAAACZbZk6pMMX+BwAAAAcAAAAUAAAALi4vdW5zZWN1cmVfZmls"
+      "ZS50eHRjb250ZW50UEsBAhQDFAAAAAAAJltmTqkwxf4HAAAABwAAABQAAAAA"
+      "AAAAAAAAAIABAAAAAC4uL3Vuc2VjdXJlX2ZpbGUudHh0UEsFBgAAAAABAAEA"
+      "QgAAADkAAAAAAA==").get()));
+
+  string extractedFile = path::join(sandbox.get(), "unsecure_file.txt");
+
+  EXPECT_ERROR(archiver::extract(path.get(), ""));
+  ASSERT_FALSE(os::exists(extractedFile));
+
+  // Just to sanity check, extract again, with the secure flag disabled.
+  EXPECT_SOME(archiver::extract(path.get(), "", 0));
+  ASSERT_TRUE(os::exists(extractedFile));
+}

Reply via email to