Skip to content

Commit 04e2f28

Browse files
further harden against malicious epubs and produce error message
1 parent ce97eb5 commit 04e2f28

File tree

1 file changed

+35
-6
lines changed

1 file changed

+35
-6
lines changed

Diff for: src/Importers/ImportEPUB.cpp

+35-6
Original file line numberDiff line numberDiff line change
@@ -425,12 +425,41 @@ void ImportEPUB::ExtractContainer()
425425
// If there is no file name then we can't do anything with it.
426426
if (!qfile_name.isEmpty()) {
427427

428-
// for security reasons we need the file path to always be inside the
429-
// target folder and not outside, so we will remove all relative upward
430-
// paths segments ".." from the file path before prepending the target
431-
// folder to create the final target path
432-
qfile_name = qfile_name.replace("../","");
433-
cp437_file_name = cp437_file_name.replace("../","");
428+
// for security reasons against maliciously crafted zip archives
429+
// we need the file path to always be inside the target folder
430+
// and not outside, so we will remove all illegal backslashes
431+
// and all relative upward paths segments "/../" from the zip's local
432+
// file name/path before prepending the target folder to create
433+
// the final path
434+
435+
QString original_path = qfile_name;
436+
bool evil_or_corrupt_epub = false;
437+
438+
if (qfile_name.contains("\\")) evil_or_corrupt_epub = true;
439+
qfile_name = "/" + qfile_name.replace("\\","");
440+
441+
if (qfile_name.contains("/../")) evil_or_corrupt_epub = true;
442+
qfile_name = qfile_name.replace("/../","/");
443+
444+
while(qfile_name.startsWith("/")) {
445+
qfile_name = qfile_name.remove(0,1);
446+
}
447+
448+
if (cp437_file_name.contains("\\")) evil_or_corrupt_epub = true;
449+
cp437_file_name = "/" + cp437_file_name.replace("\\","");
450+
451+
if (cp437_file_name.contains("/../")) evil_or_corrupt_epub = true;
452+
cp437_file_name = cp437_file_name.replace("/../","/");
453+
454+
while(cp437_file_name.startsWith("/")) {
455+
cp437_file_name = cp437_file_name.remove(0,1);
456+
}
457+
458+
if (evil_or_corrupt_epub) {
459+
unzCloseCurrentFile(zfile);
460+
unzClose(zfile);
461+
throw (EPUBLoadParseError(QString(QObject::tr("Possible evil or corrupt epub file name: %1")).arg(original_path).toStdString()));
462+
}
434463

435464
// We use the dir object to create the path in the temporary directory.
436465
// Unfortunately, we need a dir ojbect to do this as it's not a static function.

0 commit comments

Comments
 (0)