From 745e0f18bfa1195c9d285c203c28e11d21f33089 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnter=20Obiltschnig?= 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; }