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;
}