From 420614842b56211fcbcfa01f0b25055c16946f7b Mon Sep 17 00:00:00 2001 From: Seamus Lee Date: Thu, 2 Feb 2023 13:14:04 +1100 Subject: [PATCH] security/core#121 Add in hard coded list of file extensions that should be prohibited form being treated as safe no matter what Expand the list of extensions as per Tim and allow for users to define their own list via a constant --- CRM/Utils/File.php | 3 ++- tests/phpunit/CRM/Utils/FileTest.php | 34 ++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/CRM/Utils/File.php b/CRM/Utils/File.php index b9355b14c8..a822f32c6f 100644 --- a/CRM/Utils/File.php +++ b/CRM/Utils/File.php @@ -371,8 +371,9 @@ class CRM_Utils_File { } Civi::$statics[__CLASS__]['file_extensions'] = $extensions; } + $restricted = CRM_Utils_Constant::value('CIVICRM_RESTRICTED_UPLOADS', '/(php|php\d|phtml|phar|pl|py|cgi|asp|js|sh|exe|pcgi\d)/i'); // support lower and uppercase file extensions - return (bool) isset(Civi::$statics[__CLASS__]['file_extensions'][strtolower($ext)]); + return (bool) isset(Civi::$statics[__CLASS__]['file_extensions'][strtolower($ext)]) && !preg_match($restricted, strtolower($ext)); } /** diff --git a/tests/phpunit/CRM/Utils/FileTest.php b/tests/phpunit/CRM/Utils/FileTest.php index 567dc5491b..333a49613d 100644 --- a/tests/phpunit/CRM/Utils/FileTest.php +++ b/tests/phpunit/CRM/Utils/FileTest.php @@ -6,6 +6,10 @@ */ class CRM_Utils_FileTest extends CiviUnitTestCase { + public function tearDown(): void { + $this->callAPISuccess('OptionValue', 'get', ['option_group_id' => 'safe_file_extension', 'value' => 17, 'api.option_value.delete' => ['id' => "\$value.id"]]); + } + /** * Test is child path. */ @@ -646,4 +650,34 @@ class CRM_Utils_FileTest extends CiviUnitTestCase { } } + /** + * Generate examples to test the safe file extension + * @return array + */ + public static function safeFileExtensionExamples(): array { + $cases = [ + 'PDF File Extension' => ['pdf', TRUE, TRUE], + 'PHP File Extension' => ['php', FALSE, FALSE], + 'PHAR' => ['phar', FALSE, FALSE], + 'PHP5 File Extension' => ['php5', FALSE, FALSE], + ]; + return $cases; + } + + /** + * Test that modifying the safe File Extension option group still ensures some are blocked + * @dataProvider safeFileExtensionExamples + */ + public function testSafeFileExtensionValidation($extension, $standardInstallCheck, $afterModificationCheck): void { + $this->assertEquals($standardInstallCheck, CRM_Utils_File::isExtensionSafe($extension)); + $optionValue = $this->callAPISuccess('OptionValue', 'create', [ + 'option_group_id' => 'safe_file_extension', + 'label' => $extension, + 'name' => $extension, + 'value' => 17, + ]); + unset(Civi::$statics['CRM_Utils_File']['file_extensions']); + $this->assertEquals($standardInstallCheck, CRM_Utils_File::isExtensionSafe($extension)); + } + } -- 2.25.1