|
1 | 1 | /************************************************************************ |
2 | 2 | ** |
| 3 | +** Copyright (C) 2019 Kevin B. Hendricks, Stratford, Ontario Canada |
3 | 4 | ** Copyright (C) 2009, 2010, 2011 Strahinja Markovic <strahinja.markovic@gmail.com> |
4 | 5 | ** |
5 | 6 | ** This file is part of Sigil. |
@@ -715,6 +716,44 @@ bool Utility::UnZip(const QString &zippath, const QString &destpath) |
715 | 716 |
|
716 | 717 | // If there is no file name then we can't do anything with it. |
717 | 718 | if (!qfile_name.isEmpty()) { |
| 719 | + |
| 720 | + // for security reasons against maliciously crafted zip archives |
| 721 | + // we need the file path to always be inside the target folder |
| 722 | + // and not outside, so we will remove all illegal backslashes |
| 723 | + // and all relative upward paths segments "/../" from the zip's local |
| 724 | + // file name/path before prepending the target folder to create |
| 725 | + // the final path |
| 726 | + |
| 727 | + QString original_path = qfile_name; |
| 728 | + bool evil_or_corrupt_epub = false; |
| 729 | + |
| 730 | + if (qfile_name.contains("\\")) evil_or_corrupt_epub = true; |
| 731 | + qfile_name = "/" + qfile_name.replace("\\",""); |
| 732 | + |
| 733 | + if (qfile_name.contains("/../")) evil_or_corrupt_epub = true; |
| 734 | + qfile_name = qfile_name.replace("/../","/"); |
| 735 | + |
| 736 | + while(qfile_name.startsWith("/")) { |
| 737 | + qfile_name = qfile_name.remove(0,1); |
| 738 | + } |
| 739 | + |
| 740 | + if (cp437_file_name.contains("\\")) evil_or_corrupt_epub = true; |
| 741 | + cp437_file_name = "/" + cp437_file_name.replace("\\",""); |
| 742 | + |
| 743 | + if (cp437_file_name.contains("/../")) evil_or_corrupt_epub = true; |
| 744 | + cp437_file_name = cp437_file_name.replace("/../","/"); |
| 745 | + |
| 746 | + while(cp437_file_name.startsWith("/")) { |
| 747 | + cp437_file_name = cp437_file_name.remove(0,1); |
| 748 | + } |
| 749 | + |
| 750 | + if (evil_or_corrupt_epub) { |
| 751 | + unzCloseCurrentFile(zfile); |
| 752 | + unzClose(zfile); |
| 753 | + // throw (UNZIPLoadParseError(QString(QObject::tr("Possible evil or corrupt zip file name: %1")).arg(original_path).toStdString())); |
| 754 | + return false; |
| 755 | + } |
| 756 | + |
718 | 757 | // We use the dir object to create the path in the temporary directory. |
719 | 758 | // Unfortunately, we need a dir ojbect to do this as it's not a static function. |
720 | 759 | // Full file path in the temporary directory. |
|
0 commit comments