diff --git a/administrator/components/com_templates/src/Model/TemplateModel.php b/administrator/components/com_templates/src/Model/TemplateModel.php index 99819d427b408..5a31120e01437 100644 --- a/administrator/components/com_templates/src/Model/TemplateModel.php +++ b/administrator/components/com_templates/src/Model/TemplateModel.php @@ -1839,12 +1839,33 @@ public function extractArchive($file) $zip = new \ZipArchive(); if ($zip->open(Path::clean($path . '/' . $fileName)) === true) { + $realPath = realpath($path); + for ($i = 0; $i < $zip->numFiles; $i++) { $entry = $zip->getNameIndex($i); + // Prevent Zip Slip: verify that the resolved entry path stays + // within the template directory before extracting anything. + $entryPath = realpath($path . '/' . $entry); + + if ($entryPath === false) { + // Entry does not exist yet; normalise manually. + $entryPath = Path::clean($path . '/' . $entry); + } + + if ($realPath === false || strncmp($entryPath . DIRECTORY_SEPARATOR, $realPath . DIRECTORY_SEPARATOR, \strlen($realPath) + 1) !== 0) { + $app->enqueueMessage(Text::_('COM_TEMPLATES_FILE_ARCHIVE_ILLEGAL_PATH'), 'error'); + + $zip->close(); + + return false; + } + if (file_exists(Path::clean($path . '/' . $entry))) { $app->enqueueMessage(Text::_('COM_TEMPLATES_FILE_ARCHIVE_EXISTS'), 'error'); + $zip->close(); + return false; } } diff --git a/administrator/language/en-GB/com_templates.ini b/administrator/language/en-GB/com_templates.ini index f57bab877d5a4..e1b886e749beb 100644 --- a/administrator/language/en-GB/com_templates.ini +++ b/administrator/language/en-GB/com_templates.ini @@ -99,6 +99,7 @@ COM_TEMPLATES_FIELD_SOURCE_LABEL="Source Code" COM_TEMPLATES_FIELD_TEMPLATE_LABEL="Template" COM_TEMPLATES_FIELD_TITLE_LABEL="Style Name" COM_TEMPLATES_FILE_ARCHIVE_EXISTS="Some files with the same name already exist." +COM_TEMPLATES_FILE_ARCHIVE_ILLEGAL_PATH="Archive contains an illegal file path and cannot be extracted." COM_TEMPLATES_FILE_ARCHIVE_EXTRACT_FAIL="Failed to extract the archive file." COM_TEMPLATES_FILE_ARCHIVE_EXTRACT_SUCCESS="Archive file extracted." COM_TEMPLATES_FILE_ARCHIVE_NOT_FOUND="Archive file not found."