diff --git a/do-not-allow-zip-files-to-have-upward-relative-path-.patch b/do-not-allow-zip-files-to-have-upward-relative-path-.patch new file mode 100644 index 0000000..8786386 --- /dev/null +++ b/do-not-allow-zip-files-to-have-upward-relative-path-.patch @@ -0,0 +1,32 @@ +From 369eebe936e4a8c83cc54662a3412ce8bef189e4 Mon Sep 17 00:00:00 2001 +From: Kevin Hendricks +Date: Wed, 26 Jun 2019 14:33:01 -0400 +Subject: [PATCH 1/1] do not allow zip files to have upward relative path + sections + +--- + src/Importers/ImportEPUB.cpp | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/src/Importers/ImportEPUB.cpp b/src/Importers/ImportEPUB.cpp +index 722815ad4..501f49f8e 100644 +--- a/src/Importers/ImportEPUB.cpp ++++ b/src/Importers/ImportEPUB.cpp +@@ -424,6 +424,14 @@ void ImportEPUB::ExtractContainer() + + // If there is no file name then we can't do anything with it. + if (!qfile_name.isEmpty()) { ++ ++ // for security reasons we need the file path to always be inside the ++ // target folder and not outside, so we will remove all relative upward ++ // paths segments ".." from the file path before prepending the target ++ // folder to create the final target path ++ qfile_name = qfile_name.replace("../",""); ++ cp437_file_name = cp437_file_name.replace("../",""); ++ + // We use the dir object to create the path in the temporary directory. + // Unfortunately, we need a dir ojbect to do this as it's not a static function. + QDir dir(m_ExtractedFolderPath); +-- +2.20.1 + diff --git a/further-harden-against-malicious-epubs-and-produce-e.patch b/further-harden-against-malicious-epubs-and-produce-e.patch new file mode 100644 index 0000000..61082d3 --- /dev/null +++ b/further-harden-against-malicious-epubs-and-produce-e.patch @@ -0,0 +1,65 @@ +From 04e2f280cc4a0766bedcc7b9eb56449ceecc2ad4 Mon Sep 17 00:00:00 2001 +From: Kevin Hendricks +Date: Thu, 27 Jun 2019 11:47:42 -0400 +Subject: [PATCH 1/1] further harden against malicious epubs and produce error + message + +--- + src/Importers/ImportEPUB.cpp | 41 ++++++++++++++++++++++++++++++------ + 1 file changed, 35 insertions(+), 6 deletions(-) + +diff --git a/src/Importers/ImportEPUB.cpp b/src/Importers/ImportEPUB.cpp +index 501f49f8e..2f5c25f40 100644 +--- a/src/Importers/ImportEPUB.cpp ++++ b/src/Importers/ImportEPUB.cpp +@@ -425,12 +425,41 @@ void ImportEPUB::ExtractContainer() + // If there is no file name then we can't do anything with it. + if (!qfile_name.isEmpty()) { + +- // for security reasons we need the file path to always be inside the +- // target folder and not outside, so we will remove all relative upward +- // paths segments ".." from the file path before prepending the target +- // folder to create the final target path +- qfile_name = qfile_name.replace("../",""); +- cp437_file_name = cp437_file_name.replace("../",""); ++ // for security reasons against maliciously crafted zip archives ++ // we need the file path to always be inside the target folder ++ // and not outside, so we will remove all illegal backslashes ++ // and all relative upward paths segments "/../" from the zip's local ++ // file name/path before prepending the target folder to create ++ // the final path ++ ++ QString original_path = qfile_name; ++ bool evil_or_corrupt_epub = false; ++ ++ if (qfile_name.contains("\\")) evil_or_corrupt_epub = true; ++ qfile_name = "/" + qfile_name.replace("\\",""); ++ ++ if (qfile_name.contains("/../")) evil_or_corrupt_epub = true; ++ qfile_name = qfile_name.replace("/../","/"); ++ ++ while(qfile_name.startsWith("/")) { ++ qfile_name = qfile_name.remove(0,1); ++ } ++ ++ if (cp437_file_name.contains("\\")) evil_or_corrupt_epub = true; ++ cp437_file_name = "/" + cp437_file_name.replace("\\",""); ++ ++ if (cp437_file_name.contains("/../")) evil_or_corrupt_epub = true; ++ cp437_file_name = cp437_file_name.replace("/../","/"); ++ ++ while(cp437_file_name.startsWith("/")) { ++ cp437_file_name = cp437_file_name.remove(0,1); ++ } ++ ++ if (evil_or_corrupt_epub) { ++ unzCloseCurrentFile(zfile); ++ unzClose(zfile); ++ throw (EPUBLoadParseError(QString(QObject::tr("Possible evil or corrupt epub file name: %1")).arg(original_path).toStdString())); ++ } + + // We use the dir object to create the path in the temporary directory. + // Unfortunately, we need a dir ojbect to do this as it's not a static function. +-- +2.20.1 + diff --git a/harden-plugin-unzipping-to-zip-slip-attacks.patch b/harden-plugin-unzipping-to-zip-slip-attacks.patch new file mode 100644 index 0000000..3821451 --- /dev/null +++ b/harden-plugin-unzipping-to-zip-slip-attacks.patch @@ -0,0 +1,94 @@ +From 0979ba8d10c96ebca330715bfd4494ea0e019a8f Mon Sep 17 00:00:00 2001 +From: Kevin Hendricks +Date: Fri, 12 Jul 2019 14:08:44 -0400 +Subject: [PATCH 1/1] harden plugin unzipping to zip-slip attacks + +--- + src/Misc/Utility.cpp | 39 +++++++++++++++++++++++++++++++++++++++ + src/sigil_exception.h | 10 ++++++++++ + 2 files changed, 49 insertions(+) + +diff --git a/src/Misc/Utility.cpp b/src/Misc/Utility.cpp +index 81100a75c..853c4035f 100644 +--- a/src/Misc/Utility.cpp ++++ b/src/Misc/Utility.cpp +@@ -1,5 +1,6 @@ + /************************************************************************ + ** ++** Copyright (C) 2019 Kevin B. Hendricks, Stratford, Ontario Canada + ** Copyright (C) 2009, 2010, 2011 Strahinja Markovic + ** + ** This file is part of Sigil. +@@ -715,6 +716,44 @@ bool Utility::UnZip(const QString &zippath, const QString &destpath) + + // If there is no file name then we can't do anything with it. + if (!qfile_name.isEmpty()) { ++ ++ // for security reasons against maliciously crafted zip archives ++ // we need the file path to always be inside the target folder ++ // and not outside, so we will remove all illegal backslashes ++ // and all relative upward paths segments "/../" from the zip's local ++ // file name/path before prepending the target folder to create ++ // the final path ++ ++ QString original_path = qfile_name; ++ bool evil_or_corrupt_epub = false; ++ ++ if (qfile_name.contains("\\")) evil_or_corrupt_epub = true; ++ qfile_name = "/" + qfile_name.replace("\\",""); ++ ++ if (qfile_name.contains("/../")) evil_or_corrupt_epub = true; ++ qfile_name = qfile_name.replace("/../","/"); ++ ++ while(qfile_name.startsWith("/")) { ++ qfile_name = qfile_name.remove(0,1); ++ } ++ ++ if (cp437_file_name.contains("\\")) evil_or_corrupt_epub = true; ++ cp437_file_name = "/" + cp437_file_name.replace("\\",""); ++ ++ if (cp437_file_name.contains("/../")) evil_or_corrupt_epub = true; ++ cp437_file_name = cp437_file_name.replace("/../","/"); ++ ++ while(cp437_file_name.startsWith("/")) { ++ cp437_file_name = cp437_file_name.remove(0,1); ++ } ++ ++ if (evil_or_corrupt_epub) { ++ unzCloseCurrentFile(zfile); ++ unzClose(zfile); ++ // throw (UNZIPLoadParseError(QString(QObject::tr("Possible evil or corrupt zip file name: %1")).arg(original_path).toStdString())); ++ return false; ++ } ++ + // We use the dir object to create the path in the temporary directory. + // Unfortunately, we need a dir ojbect to do this as it's not a static function. + // Full file path in the temporary directory. +diff --git a/src/sigil_exception.h b/src/sigil_exception.h +index a6561d5c2..dcc0e0fca 100644 +--- a/src/sigil_exception.h ++++ b/src/sigil_exception.h +@@ -1,5 +1,6 @@ + /************************************************************************ + ** ++** Copyright (C) 2019 Kevin B. Hendricks, Stratford, Ontario Canada + ** Copyright (C) 2015 John Schember + ** Copyright (C) 2009, 2010, 2011 Strahinja Markovic + ** +@@ -132,4 +133,13 @@ public: + EPUBLoadParseError(const std::string &msg) : std::runtime_error(msg) { }; + }; + ++ ++/** ++ * Thrown for Invalid EPUB errors while loading and parsing content files. ++ */ ++class UNZIPLoadParseError : public std::runtime_error { ++public: ++ UNZIPLoadParseError(const std::string &msg) : std::runtime_error(msg) { }; ++}; ++ + #endif // SG_EXCEPTION_H +-- +2.20.1 + diff --git a/sigil.spec b/sigil.spec index 1b9595f..8d9ecd1 100644 --- a/sigil.spec +++ b/sigil.spec @@ -2,7 +2,7 @@ Name: sigil Version: 0.9.14 -Release: 1 +Release: 2 Summary: WYSIWYG ebook editor License: GPLv3+ URL: https://sigil-ebook.com/ @@ -15,7 +15,11 @@ Patch2: %{name}-0.9.3-global-plugin-support.patch Patch3: %{name}-0.9.13-minizip2.patch # https://bugzilla.redhat.com/show_bug.cgi?id=2083977 Patch4: %{name}-0.9.14-python311.patch -BuildRequires: make +Patch5: do-not-allow-zip-files-to-have-upward-relative-path-.patch +Patch6: further-harden-against-malicious-epubs-and-produce-e.patch +Patch7: harden-plugin-unzipping-to-zip-slip-attacks.patch + +BuildRequires: make BuildRequires: cmake BuildRequires: qt5-qtbase-devel BuildRequires: qt5-qtwebkit-devel @@ -80,6 +84,9 @@ BuildArch: noarch %patch3 -p1 -b .mz %endif %patch4 -p1 +%patch5 -p1 +%patch6 -p1 +%patch7 -p1 sed -i 's|/lib/sigil|/%{_lib}/sigil|' \ CMakeLists.txt src/CMakeLists.txt \ src/Resource_Files/bash/sigil-sh_install @@ -164,6 +171,9 @@ appstream-util validate-relax --nonet \ %changelog +* Thu Nov 16 2023 lvgenggeng - 0.9.14-2 +- fix CVE-2019-14452 + * Fri May 26 2023 wangtaozhi - 0.9.14-1 - Package init