Blob Blame History Raw
From 745e0f18bfa1195c9d285c203c28e11d21f33089 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?G=C3=BCnter=20Obiltschnig?= <guenter.obiltschnig@appinf.com>
Date: Thu, 2 Nov 2017 09:40:25 +0100
Subject: [PATCH] fix GH# 1968: Zip Decompress Parent Path Injection

---
 CHANGELOG                         |  6 ++++++
 DLLVersion.rc                     |  4 ++--
 Foundation/include/Poco/Version.h |  2 +-
 VERSION                           |  2 +-
 Zip/src/Decompress.cpp            |  4 ++--
 Zip/src/ZipCommon.cpp             | 26 ++++++++++++++++++++++----
 doc/99100-ReleaseNotes.page       |  7 +++++++
 7 files changed, 41 insertions(+), 10 deletions(-)

diff --git a/Zip/src/Decompress.cpp b/Zip/src/Decompress.cpp
index e01f47e9de..d37b199e70 100644
--- a/Zip/src/Decompress.cpp
+++ b/Zip/src/Decompress.cpp
@@ -82,7 +82,7 @@ bool Decompress::handleZipEntry(std::istream& zipStream, const ZipLocalFileHeade
 		{
 			std::string dirName = hdr.getFileName();
 			if (!ZipCommon::isValidPath(dirName))
-				throw ZipException("Illegal entry name " + dirName + " containing parent directory reference");
+				throw ZipException("Illegal entry name", dirName);
 			Poco::Path dir(_outDir, dirName);
 			dir.makeDirectory();
 			Poco::File aFile(dir);
@@ -102,7 +102,7 @@ bool Decompress::handleZipEntry(std::istream& zipStream, const ZipLocalFileHeade
 		}
 
 		if (!ZipCommon::isValidPath(fileName))
-			throw ZipException("Illegal entry name " + fileName + " containing parent directory reference");
+			throw ZipException("Illegal entry name", fileName);
 
 		Poco::Path file(fileName);
 		file.makeFile();
diff --git a/Zip/src/ZipCommon.cpp b/Zip/src/ZipCommon.cpp
index fade822512..8241258399 100644
--- a/Zip/src/ZipCommon.cpp
+++ b/Zip/src/ZipCommon.cpp
@@ -15,6 +15,7 @@
 
 
 #include "Poco/Zip/ZipCommon.h"
+#include "Poco/Path.h"
 
 
 namespace Poco {
@@ -23,16 +24,33 @@ namespace Zip {
 
 bool ZipCommon::isValidPath(const std::string& path)
 {
+	try
+	{
+		if (Path(path, Path::PATH_UNIX).isAbsolute() || Path(path, Path::PATH_WINDOWS).isAbsolute())
+			return false;
+	}
+	catch (...)
+	{
+		return false;
+	}
+
 	if (path == "..")
 		return false;
-	if (path.compare(0, 3, "../") == 0)
+	if ((path.size() >= 3) && path.compare(0, 3, "../") == 0)
+		return false;
+	if ((path.size() >= 3) && path.compare(0, 3, "..\\") == 0)
 		return false;
-	if (path.compare(0, 3, "..\\") == 0)
+	if (path.find("/../") != std::string::npos)
 		return false;
-	if (path.find("/..") != std::string::npos)
+	if (path.find("\\..\\") != std::string::npos)
 		return false;
-	if (path.find("\\..") != std::string::npos)
+	if (path.find("/..\\") != std::string::npos)
 		return false;
+	if (path.find("\\../") != std::string::npos)
+		return false;
+	if ((path.size() >= 2) && path.compare(0, 2, "~/") == 0)
+		return false;
+
 	return true;
 }