Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
"baserproject/bc-widget-area": "5.3.0"
},
"suggest": {
"ext-fileinfo": "Enables validating that an uploaded plugin/theme archive is really a ZIP file before extracting it.",
"markstory/asset_compress": "An asset compression plugin which provides file concatenation and a flexible filter system for preprocessing and minification.",
"dereuromark/cakephp-ide-helper": "After baking your code, this keeps your annotations in sync with the code evolving from there on for maximum IDE and PHPStan/Psalm compatibility.",
"phpstan/phpstan": "PHPStan focuses on finding errors in your code without actually running it. It catches whole classes of bugs even before you write tests for the code.",
Expand Down
3 changes: 3 additions & 0 deletions plugins/baser-core/composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@
"vierge-noire/cakephp-test-suite-light": "~3.0.0",
"ext-xdebug": "*"
},
"suggest": {
"ext-fileinfo": "Enables validating that an uploaded plugin/theme archive is really a ZIP file before extracting it."
},
"autoload": {
"psr-4": {
"BaserCore\\": "src",
Expand Down
6 changes: 5 additions & 1 deletion plugins/baser-core/resources/locales/en/baser_core.po
Original file line number Diff line number Diff line change
Expand Up @@ -3396,7 +3396,11 @@ msgstr "Error occurred when processing. Please contact the Plugin’s developer.
msgid "サーバに設定されているサイズ制限を超えています。"
msgstr "The size is exceeding the size restriction of the server."

#: plugins/baser-core/src/Service/PluginsService.php:705
#: plugins/baser-core/src/Service/PluginsService.php:733
msgid "ZIPファイルをアップロードしてください。"
msgstr "Please upload a ZIP file."

#: plugins/baser-core/src/Service/PluginsService.php:738
#: plugins/baser-core/src/Service/ThemesService.php:156
#: plugins/baser-core/src/Service/UtilitiesService.php:428
msgid "アップロードしたZIPファイルの展開に失敗しました。"
Expand Down
25 changes: 22 additions & 3 deletions plugins/baser-core/src/Service/PluginsService.php
Original file line number Diff line number Diff line change
Expand Up @@ -721,9 +721,28 @@ public function add(array $postData)
// パストラバーサル対策: クライアント提供のファイル名から basename() でディレクトリ要素を除去する
$name = basename($postData['file']->getClientFileName());
$postData['file']->moveTo(TMP . $name);
$zip = new BcZip();
if (!$zip->extract(TMP . $name, TMP)) {
throw new BcException(__d('baser_core', 'アップロードしたZIPファイルの展開に失敗しました。'));
try {
// アップロードされたファイルが ZIP であるかを内容から判定する
// ext-fileinfo が無効な環境では判定をスキップし、展開時のエラーに委ねる
if (class_exists('finfo')) {
$finfo = new \finfo(FILEINFO_MIME_TYPE);
$mimeType = $finfo->file(TMP . $name);
// finfo はファイルの内容から判定するため通常は application/zip を返す
// application/x-zip-compressed は一部環境の libmagic に対する保険
if (!in_array($mimeType, ['application/zip', 'application/x-zip-compressed'], true)) {
throw new BcException(__d('baser_core', 'ZIPファイルをアップロードしてください。'));
}
}
$zip = new BcZip();
if (!$zip->extract(TMP . $name, TMP)) {
throw new BcException(__d('baser_core', 'アップロードしたZIPファイルの展開に失敗しました。'));
}
} catch (BcException $e) {
// 展開できなかったテンポラリファイルを残さない
if (file_exists(TMP . $name)) {
unlink(TMP . $name);
}
throw $e;
}
$srcDirName = $zip->topArchiveName;
$dstName = $srcName = Inflector::camelize($srcDirName);
Expand Down
35 changes: 35 additions & 0 deletions plugins/baser-core/tests/TestCase/Service/PluginsServiceTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -877,4 +877,39 @@ public function test_getCoreUpdate_vulnerability()

$this->assertFalse(file_exists($rceFile), 'getCoreUpdate でOSコマンドインジェクションが発生しました');
}

/**
* test add ZIP以外のファイルをアップロードした場合
* @return void
*/
public function test_addRejectsNonZipFile()
{
$zipSrcPath = TMP . 'zip' . DS;
$folder = new BcFolder($zipSrcPath);
$folder->create();
//架空のプラグイン名を指定して、ZIP以外のファイルを作成
$plugin = 'NotZipPlugin';
$testFile = $zipSrcPath . $plugin . '.zip';
file_put_contents($testFile, 'This is not a zip file.');
$size = filesize($testFile);

$this->setUploadFileToRequest('file', $testFile);
$files = new UploadedFile(
$testFile,
$size,
UPLOAD_ERR_OK,
$plugin . '.zip',
'text/plain'
);

$this->expectException("BaserCore\Error\BcException");
$this->expectExceptionMessage("ZIPファイルをアップロードしてください。");
try {
$this->Plugins->add(["file" => $files]);
} finally {
// アップロードされた一時ファイルが削除されていること
$this->assertFileDoesNotExist(TMP . $plugin . '.zip');
$folder->delete();
}
}
}
Loading