Signed-off-by: lvgenggeng <lvgenggeng@uniontech.com> (cherry picked from commit 353d0a2d6b6b6264e7373fb7e69869e4cd981918)
95 lines
3.6 KiB
Diff
95 lines
3.6 KiB
Diff
From 0979ba8d10c96ebca330715bfd4494ea0e019a8f Mon Sep 17 00:00:00 2001
|
|
From: Kevin Hendricks <kevin.b.hendricks@icloud.com>
|
|
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 <strahinja.markovic@gmail.com>
|
|
**
|
|
** 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 <john@nachtimwald.com>
|
|
** Copyright (C) 2009, 2010, 2011 Strahinja Markovic <strahinja.markovic@gmail.com>
|
|
**
|
|
@@ -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
|
|
|