Sophie

Sophie

distrib > Mageia > 9 > armv7hl > by-pkgid > b07f88bf006a5198893fab882807d596 > files > 6

flightcrew-0.9.0-23.mga9.src.rpm

From 2e0286e78a117553af833b034aa08a2e919d08a5 Mon Sep 17 00:00:00 2001
From: Kevin Hendricks <kevin.b.hendricks@icloud.com>
Date: Thu, 27 Jun 2019 11:06:12 -0400
Subject: [PATCH] further harden zip extraction to always be safe

---
 src/zipios/src/zipextraction.cpp | 35 ++++++++++++++++++++++++--------
 1 file changed, 27 insertions(+), 8 deletions(-)

diff --git a/src/zipios/src/zipextraction.cpp b/src/zipios/src/zipextraction.cpp
index 0e238c8..5783b79 100644
--- a/src/zipios/src/zipextraction.cpp
+++ b/src/zipios/src/zipextraction.cpp
@@ -73,17 +73,36 @@ void ExtractZipToFolder( const fs::path &path_to_zip, const fs::path &path_to_fo
     {
         boost::scoped_ptr< std::istream > stream( zip.getInputStream( *it ) );
 
-        // for security reasons need to force any relative path
-        // to be inside the destination folder and not anyplace else
-        // do this by removing any and all upward relative path segments as
-	// epubs are not general zip archives used for backup
+        // for security against maliciously crafted epubs
+	// we need to force all files extracted from the epub/zip to be safely inside
+        // the destination folder and not anyplace else.
+
+        // First remove all illegal backslash characters (escapes) - see Zip spec
+        // Next remove any and all upward relative path segments "/../"
+        // Finally remove any leading "/" characters to create a safer relative path
+
+	// epubs zips are not general zip archives so symlinks and upward
+        // relative path segments need not be supported.
+
 	string azipfilepath = (*it)->getName();
-        size_t index = azipfilepath.find("../", 0);
+        size_t n = azipfilepath.length();
+
+        // stripping out any backslashes during copy
+	string securefilepath = "/";
+	securefilepath.reserve(n+1);
+        for (size_t i=0; i < n; i++) {
+	    if (azipfilepath[i] != '\\') securefilepath.append(1, azipfilepath[i]);
+	}
+        // now replace all upward path segments "/../" with "/"
+        size_t index = securefilepath.find("/../", 0);
         while(index != std::string::npos) {
-	    azipfilepath.replace(index, 3,"");
-	    index = azipfilepath.find("../", 0);
+	    securefilepath.replace(index, 4,"/");
+	    index = securefilepath.find("/../", index);
 	}
-        fs::path new_file_path = path_to_folder / azipfilepath;
+        // finally remove any leading "/"
+        securefilepath.erase(0,securefilepath.find_first_not_of("/"));
+
+        fs::path new_file_path = path_to_folder / securefilepath;
 
         CreateFilepath( new_file_path );
         WriteEntryToFile( *stream, new_file_path );