diff --git a/composer.json b/composer.json index 3da6be3..5d90152 100644 --- a/composer.json +++ b/composer.json @@ -2,7 +2,7 @@ "name": "magento/magento-cloud-patches", "description": "Provides critical fixes for Magento 2 Enterprise Edition", "type": "magento2-component", - "version": "1.1.1", + "version": "1.1.2", "license": "OSL-3.0", "repositories": { "repo.magento.com": { diff --git a/patches.json b/patches.json index 637d3e1..8f41963 100644 --- a/patches.json +++ b/patches.json @@ -280,6 +280,18 @@ }, "Enhanced Layout Cache Efficiency (memory usage reduced)": { ">=2.4.4 <2.4.7": "MCLOUD-11514__enhanced_layout_cache_efficiency__2.4.6-p3.patch" + }, + "Patch for CVE-2024-34102 - CosmicSting": { + ">=2.4.4 <2.4.4-p8": "MCLOUD-12969__Patch_for_CVE_2024_34102_CosmicSting__2.4.4.patch", + ">=2.4.5 <2.4.5-p7": "MCLOUD-12969__Patch_for_CVE_2024_34102_CosmicSting__2.4.5.patch", + ">=2.4.6 <2.4.6-p5": "MCLOUD-12969__Patch_for_CVE_2024_34102_CosmicSting__2.4.6.patch", + "2.4.7": "MCLOUD-12969__Patch_for_CVE_2024_34102_CosmicSting__2.4.7.patch" + }, + "Patch for CVE-2024-34102 - KeyRotation": { + ">=2.4.4 <2.4.4-p10": "MCLOUD-12969__Patch_for_CVE_2024_34102_KeyRotation__2.4.4.patch", + ">=2.4.5 <2.4.5-p9": "MCLOUD-12969__Patch_for_CVE_2024_34102_KeyRotation__2.4.5.patch", + ">=2.4.6 <2.4.6-p7": "MCLOUD-12969__Patch_for_CVE_2024_34102_KeyRotation__2.4.6.patch", + ">=2.4.7 <2.4.7-p2": "MCLOUD-12969__Patch_for_CVE_2024_34102_KeyRotation__2.4.7.patch" } }, "magento/module-paypal": { diff --git a/patches/MCLOUD-12969__Patch_for_CVE_2024_34102_CosmicSting__2.4.4.patch b/patches/MCLOUD-12969__Patch_for_CVE_2024_34102_CosmicSting__2.4.4.patch new file mode 100644 index 0000000..5175edb --- /dev/null +++ b/patches/MCLOUD-12969__Patch_for_CVE_2024_34102_CosmicSting__2.4.4.patch @@ -0,0 +1,62 @@ +diff --git a/vendor/magento/theme-frontend-blank/i18n/en_US.csv b/vendor/magento/theme-frontend-blank/i18n/en_US.csv +index a491a567a37..5e8bef787d2 100644 +--- a/vendor/magento/theme-frontend-blank/i18n/en_US.csv ++++ b/vendor/magento/theme-frontend-blank/i18n/en_US.csv +@@ -4,3 +4,4 @@ Summary,Summary + Menu,Menu + Account,Account + Settings,Settings ++"Invalid data type","Invalid data type" +diff --git a/vendor/magento/theme-frontend-luma/i18n/en_US.csv b/vendor/magento/theme-frontend-luma/i18n/en_US.csv +index 7bf9e0afaf0..00493cc05ba 100644 +--- a/vendor/magento/theme-frontend-luma/i18n/en_US.csv ++++ b/vendor/magento/theme-frontend-luma/i18n/en_US.csv +@@ -54,3 +54,4 @@ Footer,Footer + "Update to your %store_name shipment","Update to your %store_name shipment" + "Address Book","Address Book" + "Account Information","Account Information" ++"Invalid data type","Invalid data type" +diff --git a/vendor/magento/framework/Webapi/ServiceInputProcessor.php b/vendor/magento/framework/Webapi/ServiceInputProcessor.php +index 908a4e70140..cc019845b58 100644 +--- a/vendor/magento/framework/Webapi/ServiceInputProcessor.php ++++ b/vendor/magento/framework/Webapi/ServiceInputProcessor.php +@@ -153,6 +153,7 @@ class ServiceInputProcessor implements ServicePayloadConverterInterface + * @return \Magento\Framework\Reflection\NameFinder + * + * @deprecated 100.1.0 ++ * @see nothing + */ + private function getNameFinder() + { +@@ -261,6 +262,7 @@ class ServiceInputProcessor implements ServicePayloadConverterInterface + * @throws \Exception + * @throws SerializationException + * @SuppressWarnings(PHPMD.CyclomaticComplexity) ++ * @SuppressWarnings(PHPMD.NPathComplexity) + */ + protected function _createFromArray($className, $data) + { +@@ -268,6 +270,12 @@ class ServiceInputProcessor implements ServicePayloadConverterInterface + // convert to string directly to avoid situations when $className is object + // which implements __toString method like \ReflectionObject + $className = (string) $className; ++ if (is_subclass_of($className, \SimpleXMLElement::class) ++ || is_subclass_of($className, \DOMElement::class)) { ++ throw new SerializationException( ++ new Phrase('Invalid data type') ++ ); ++ } + $class = new ClassReflection($className); + if (is_subclass_of($className, self::EXTENSION_ATTRIBUTES_TYPE)) { + $className = substr($className, 0, -strlen('Interface')); +diff --git a/vendor/magento/module-jwt-user-token/Model/SecretBasedJwksFactory.php b/vendor/magento/module-jwt-user-token/Model/SecretBasedJwksFactory.php +--- a/vendor/magento/module-jwt-user-token/Model/SecretBasedJwksFactory.php (revision 022e64b08a88658667bc2d6b922eada2b7910965) ++++ b/vendor/magento/module-jwt-user-token/Model/SecretBasedJwksFactory.php (revision 8d2b0c1c6b421cdcd7f62a48a5edc9b0211d92a2) +@@ -35,6 +35,7 @@ + public function __construct(DeploymentConfig $deploymentConfig, JwkFactory $jwkFactory) + { + $this->keys = preg_split('/\s+/s', trim((string)$deploymentConfig->get('crypt/key'))); ++ $this->keys = [end($this->keys)]; + //Making sure keys are large enough. + foreach ($this->keys as &$key) { + $key = str_pad($key, 2048, '&', STR_PAD_BOTH); diff --git a/patches/MCLOUD-12969__Patch_for_CVE_2024_34102_CosmicSting__2.4.5.patch b/patches/MCLOUD-12969__Patch_for_CVE_2024_34102_CosmicSting__2.4.5.patch new file mode 100644 index 0000000..e5740c2 --- /dev/null +++ b/patches/MCLOUD-12969__Patch_for_CVE_2024_34102_CosmicSting__2.4.5.patch @@ -0,0 +1,62 @@ +diff --git a/vendor/magento/theme-frontend-blank/i18n/en_US.csv b/vendor/magento/theme-frontend-blank/i18n/en_US.csv +index a491a567a37..5e8bef787d2 100644 +--- a/vendor/magento/theme-frontend-blank/i18n/en_US.csv ++++ b/vendor/magento/theme-frontend-blank/i18n/en_US.csv +@@ -4,3 +4,4 @@ Summary,Summary + Menu,Menu + Account,Account + Settings,Settings ++"Invalid data type","Invalid data type" +diff --git a/vendor/magento/theme-frontend-luma/i18n/en_US.csv b/vendor/magento/theme-frontend-luma/i18n/en_US.csv +index 7bf9e0afaf0..00493cc05ba 100644 +--- a/vendor/magento/theme-frontend-luma/i18n/en_US.csv ++++ b/vendor/magento/theme-frontend-luma/i18n/en_US.csv +@@ -54,3 +54,4 @@ Footer,Footer + "Update to your %store_name shipment","Update to your %store_name shipment" + "Address Book","Address Book" + "Account Information","Account Information" ++"Invalid data type","Invalid data type" +diff --git a/vendor/magento/framework/Webapi/ServiceInputProcessor.php b/vendor/magento/framework/Webapi/ServiceInputProcessor.php +index a5e881f4be5..a60f1dd7ba1 100644 +--- a/vendor/magento/framework/Webapi/ServiceInputProcessor.php ++++ b/vendor/magento/framework/Webapi/ServiceInputProcessor.php +@@ -153,6 +153,7 @@ class ServiceInputProcessor implements ServicePayloadConverterInterface + * @return \Magento\Framework\Reflection\NameFinder + * + * @deprecated 100.1.0 ++ * @see nothing + */ + private function getNameFinder() + { +@@ -261,6 +262,7 @@ class ServiceInputProcessor implements ServicePayloadConverterInterface + * @throws \Exception + * @throws SerializationException + * @SuppressWarnings(PHPMD.CyclomaticComplexity) ++ * @SuppressWarnings(PHPMD.NPathComplexity) + */ + protected function _createFromArray($className, $data) + { +@@ -268,6 +270,12 @@ class ServiceInputProcessor implements ServicePayloadConverterInterface + // convert to string directly to avoid situations when $className is object + // which implements __toString method like \ReflectionObject + $className = (string) $className; ++ if (is_subclass_of($className, \SimpleXMLElement::class) ++ || is_subclass_of($className, \DOMElement::class)) { ++ throw new SerializationException( ++ new Phrase('Invalid data type') ++ ); ++ } + $class = new ClassReflection($className); + if (is_subclass_of($className, self::EXTENSION_ATTRIBUTES_TYPE)) { + $className = substr($className, 0, -strlen('Interface')); +diff --git a/vendor/magento/module-jwt-user-token/Model/SecretBasedJwksFactory.php b/vendor/magento/module-jwt-user-token/Model/SecretBasedJwksFactory.php +--- a/vendor/magento/module-jwt-user-token/Model/SecretBasedJwksFactory.php (revision 022e64b08a88658667bc2d6b922eada2b7910965) ++++ b/vendor/magento/module-jwt-user-token/Model/SecretBasedJwksFactory.php (revision 8d2b0c1c6b421cdcd7f62a48a5edc9b0211d92a2) +@@ -35,6 +35,7 @@ + public function __construct(DeploymentConfig $deploymentConfig, JwkFactory $jwkFactory) + { + $this->keys = preg_split('/\s+/s', trim((string)$deploymentConfig->get('crypt/key'))); ++ $this->keys = [end($this->keys)]; + //Making sure keys are large enough. + foreach ($this->keys as &$key) { + $key = str_pad($key, 2048, '&', STR_PAD_BOTH); diff --git a/patches/MCLOUD-12969__Patch_for_CVE_2024_34102_CosmicSting__2.4.6.patch b/patches/MCLOUD-12969__Patch_for_CVE_2024_34102_CosmicSting__2.4.6.patch new file mode 100644 index 0000000..1296cc0 --- /dev/null +++ b/patches/MCLOUD-12969__Patch_for_CVE_2024_34102_CosmicSting__2.4.6.patch @@ -0,0 +1,46 @@ +diff --git a/vendor/magento/theme-frontend-blank/i18n/en_US.csv b/vendor/magento/theme-frontend-blank/i18n/en_US.csv +index a491a567a37..5e8bef787d2 100644 +--- a/vendor/magento/theme-frontend-blank/i18n/en_US.csv ++++ b/vendor/magento/theme-frontend-blank/i18n/en_US.csv +@@ -4,3 +4,4 @@ Summary,Summary + Menu,Menu + Account,Account + Settings,Settings ++"Invalid data type","Invalid data type" +diff --git a/vendor/magento/theme-frontend-luma/i18n/en_US.csv b/vendor/magento/theme-frontend-luma/i18n/en_US.csv +index 7bf9e0afaf0..00493cc05ba 100644 +--- a/vendor/magento/theme-frontend-luma/i18n/en_US.csv ++++ b/vendor/magento/theme-frontend-luma/i18n/en_US.csv +@@ -54,3 +54,4 @@ Footer,Footer + "Update to your %store_name shipment","Update to your %store_name shipment" + "Address Book","Address Book" + "Account Information","Account Information" ++"Invalid data type","Invalid data type" +diff --git a/vendor/magento/framework/Webapi/ServiceInputProcessor.php b/vendor/magento/framework/Webapi/ServiceInputProcessor.php +index 9d7fd443508..65987772c23 100644 +--- a/vendor/magento/framework/Webapi/ServiceInputProcessor.php ++++ b/vendor/magento/framework/Webapi/ServiceInputProcessor.php +@@ -275,6 +275,12 @@ class ServiceInputProcessor implements ServicePayloadConverterInterface + // convert to string directly to avoid situations when $className is object + // which implements __toString method like \ReflectionObject + $className = (string) $className; ++ if (is_subclass_of($className, \SimpleXMLElement::class) ++ || is_subclass_of($className, \DOMElement::class)) { ++ throw new SerializationException( ++ new Phrase('Invalid data type') ++ ); ++ } + $class = new ClassReflection($className); + if (is_subclass_of($className, self::EXTENSION_ATTRIBUTES_TYPE)) { + $className = substr($className, 0, -strlen('Interface')); +diff --git a/vendor/magento/module-jwt-user-token/Model/SecretBasedJwksFactory.php b/vendor/magento/module-jwt-user-token/Model/SecretBasedJwksFactory.php +--- a/vendor/magento/module-jwt-user-token/Model/SecretBasedJwksFactory.php (revision 022e64b08a88658667bc2d6b922eada2b7910965) ++++ b/vendor/magento/module-jwt-user-token/Model/SecretBasedJwksFactory.php (revision 8d2b0c1c6b421cdcd7f62a48a5edc9b0211d92a2) +@@ -35,6 +35,7 @@ + public function __construct(DeploymentConfig $deploymentConfig, JwkFactory $jwkFactory) + { + $this->keys = preg_split('/\s+/s', trim((string)$deploymentConfig->get('crypt/key'))); ++ $this->keys = [end($this->keys)]; + //Making sure keys are large enough. + foreach ($this->keys as &$key) { + $key = str_pad($key, 2048, '&', STR_PAD_BOTH); diff --git a/patches/MCLOUD-12969__Patch_for_CVE_2024_34102_CosmicSting__2.4.7.patch b/patches/MCLOUD-12969__Patch_for_CVE_2024_34102_CosmicSting__2.4.7.patch new file mode 100644 index 0000000..4f23fb7 --- /dev/null +++ b/patches/MCLOUD-12969__Patch_for_CVE_2024_34102_CosmicSting__2.4.7.patch @@ -0,0 +1,55 @@ +diff --git a/vendor/magento/theme-adminhtml-backend/i18n/en_US.csv b/vendor/magento/theme-adminhtml-backend/i18n/en_US.csv +index 2708988e731..885d0056d4b 100644 +--- a/vendor/magento/theme-adminhtml-backend/i18n/en_US.csv ++++ b/vendor/magento/theme-adminhtml-backend/i18n/en_US.csv +@@ -547,3 +547,4 @@ Dashboard,Dashboard + "Web Section","Web Section" + "Store Email Addresses Section","Store Email Addresses Section" + "Email to a Friend","Email to a Friend" ++"Invalid data type","Invalid data type" +diff --git a/vendor/magento/theme-frontend-blank/i18n/en_US.csv b/vendor/magento/theme-frontend-blank/i18n/en_US.csv +index 025866f654d..cc02ab5ac90 100644 +--- a/vendor/magento/theme-frontend-blank/i18n/en_US.csv ++++ b/vendor/magento/theme-frontend-blank/i18n/en_US.csv +@@ -439,3 +439,4 @@ Summary,Summary + Test,Test + test,test + Two,Two ++"Invalid data type","Invalid data type" +diff --git a/vendor/magento/theme-frontend-luma/i18n/en_US.csv b/vendor/magento/theme-frontend-luma/i18n/en_US.csv +index e80cb58e679..3d0e8ab2650 100644 +--- a/vendor/magento/theme-frontend-luma/i18n/en_US.csv ++++ b/vendor/magento/theme-frontend-luma/i18n/en_US.csv +@@ -489,3 +489,4 @@ Remove,Remove + Test,Test + test,test + Two,Two ++"Invalid data type","Invalid data type" +diff --git a/vendor/magento/framework/Webapi/ServiceInputProcessor.php b/vendor/magento/framework/Webapi/ServiceInputProcessor.php +index cd7960409e1..df31058ff32 100644 +--- a/vendor/magento/framework/Webapi/ServiceInputProcessor.php ++++ b/vendor/magento/framework/Webapi/ServiceInputProcessor.php +@@ -278,6 +278,12 @@ class ServiceInputProcessor implements ServicePayloadConverterInterface, ResetAf + // convert to string directly to avoid situations when $className is object + // which implements __toString method like \ReflectionObject + $className = (string) $className; ++ if (is_subclass_of($className, \SimpleXMLElement::class) ++ || is_subclass_of($className, \DOMElement::class)) { ++ throw new SerializationException( ++ new Phrase('Invalid data type') ++ ); ++ } + $class = new ClassReflection($className); + if (is_subclass_of($className, self::EXTENSION_ATTRIBUTES_TYPE)) { + $className = substr($className, 0, -strlen('Interface')); +diff --git a/vendor/magento/module-jwt-user-token/Model/SecretBasedJwksFactory.php b/vendor/magento/module-jwt-user-token/Model/SecretBasedJwksFactory.php +--- a/vendor/magento/module-jwt-user-token/Model/SecretBasedJwksFactory.php (revision 022e64b08a88658667bc2d6b922eada2b7910965) ++++ b/vendor/magento/module-jwt-user-token/Model/SecretBasedJwksFactory.php (revision 8d2b0c1c6b421cdcd7f62a48a5edc9b0211d92a2) +@@ -35,6 +35,7 @@ + public function __construct(DeploymentConfig $deploymentConfig, JwkFactory $jwkFactory) + { + $this->keys = preg_split('/\s+/s', trim((string)$deploymentConfig->get('crypt/key'))); ++ $this->keys = [end($this->keys)]; + //Making sure keys are large enough. + foreach ($this->keys as &$key) { + $key = str_pad($key, 2048, '&', STR_PAD_BOTH); diff --git a/patches/MCLOUD-12969__Patch_for_CVE_2024_34102_KeyRotation__2.4.4.patch b/patches/MCLOUD-12969__Patch_for_CVE_2024_34102_KeyRotation__2.4.4.patch new file mode 100644 index 0000000..94adc61 --- /dev/null +++ b/patches/MCLOUD-12969__Patch_for_CVE_2024_34102_KeyRotation__2.4.4.patch @@ -0,0 +1,163 @@ +diff --git a/vendor/magento/module-encryption-key/Console/Command/UpdateEncryptionKeyCommand.php b/vendor/magento/module-encryption-key/Console/Command/UpdateEncryptionKeyCommand.php +new file mode 100644 +index 0000000000000..8777f99139edc +--- /dev/null ++++ b/vendor/magento/module-encryption-key/Console/Command/UpdateEncryptionKeyCommand.php +@@ -0,0 +1,141 @@ ++encryptor = $encryptor; ++ $this->cache = $cache; ++ $this->writer = $writer; ++ $this->random = $random; ++ ++ parent::__construct(); ++ } ++ ++ /** ++ * @inheritDoc ++ */ ++ protected function configure() ++ { ++ $this->setName('encryption:key:change'); ++ $this->setDescription('Change the encryption key inside the env.php file.'); ++ $this->addOption( ++ 'key', ++ 'k', ++ InputOption::VALUE_OPTIONAL, ++ 'Key has to be a 32 characters long string. If not provided, a random key will be generated.' ++ ); ++ ++ parent::configure(); ++ } ++ ++ /** ++ * @inheritDoc ++ */ ++ protected function execute(InputInterface $input, OutputInterface $output) ++ { ++ try { ++ $key = $input->getOption('key'); ++ ++ if (!empty($key)) { ++ $this->encryptor->validateKey($key); ++ } ++ ++ $this->updateEncryptionKey($key); ++ $this->cache->clean(); ++ ++ $output->writeln('Encryption key has been updated successfully.'); ++ ++ return Cli::RETURN_SUCCESS; ++ } catch (\Exception $e) { ++ $output->writeln('' . $e->getMessage() . ''); ++ return Cli::RETURN_FAILURE; ++ } ++ } ++ ++ /** ++ * Update encryption key ++ * ++ * @param string|null $key ++ * @return void ++ * @throws FileSystemException ++ */ ++ private function updateEncryptionKey(string $key = null): void ++ { ++ // prepare new key, encryptor and new configuration segment ++ if (!$this->writer->checkIfWritable()) { ++ throw new FileSystemException(__('Deployment configuration file is not writable.')); ++ } ++ ++ if (null === $key) { ++ // md5() here is not for cryptographic use. It used for generate encryption key itself ++ // and do not encrypt any passwords ++ // phpcs:ignore Magento2.Security.InsecureFunction ++ $key = md5($this->random->getRandomString(ConfigOptionsListConstants::STORE_KEY_RANDOM_STRING_SIZE)); ++ } ++ ++ $this->encryptor->setNewKey($key); ++ ++ $encryptSegment = new ConfigData(ConfigFilePool::APP_ENV); ++ $encryptSegment->set(ConfigOptionsListConstants::CONFIG_PATH_CRYPT_KEY, $this->encryptor->exportKeys()); ++ ++ $configData = [$encryptSegment->getFileKey() => $encryptSegment->getData()]; ++ ++ $this->writer->saveConfig($configData); ++ } ++} +diff --git a/vendor/magento/module-encryption-key/etc/di.xml b/vendor/magento/module-encryption-key/etc/di.xml +index b4e471f4e40ef..495234759a7f8 100644 +--- a/vendor/magento/module-encryption-key/etc/di.xml ++++ b/vendor/magento/module-encryption-key/etc/di.xml +@@ -11,4 +11,11 @@ + Magento\Config\Model\Config\Structure\Proxy + + ++ ++ ++ ++ Magento\EncryptionKey\Console\Command\UpdateEncryptionKeyCommand ++ ++ ++ + diff --git a/patches/MCLOUD-12969__Patch_for_CVE_2024_34102_KeyRotation__2.4.5.patch b/patches/MCLOUD-12969__Patch_for_CVE_2024_34102_KeyRotation__2.4.5.patch new file mode 100644 index 0000000..29adfc3 --- /dev/null +++ b/patches/MCLOUD-12969__Patch_for_CVE_2024_34102_KeyRotation__2.4.5.patch @@ -0,0 +1,162 @@ +diff --git a/vendor/magento/module-encryption-key/Console/Command/UpdateEncryptionKeyCommand.php b/vendor/magento/module-encryption-key/Console/Command/UpdateEncryptionKeyCommand.php +new file mode 100644 +index 0000000000000..351379552e104 +--- /dev/null ++++ b/vendor/magento/module-encryption-key/Console/Command/UpdateEncryptionKeyCommand.php +@@ -0,0 +1,140 @@ ++encryptor = $encryptor; ++ $this->cache = $cache; ++ $this->writer = $writer; ++ $this->random = $random; ++ ++ parent::__construct(); ++ } ++ ++ /** ++ * @inheritDoc ++ */ ++ protected function configure() ++ { ++ $this->setName('encryption:key:change'); ++ $this->setDescription('Change the encryption key inside the env.php file.'); ++ $this->addOption( ++ 'key', ++ 'k', ++ InputOption::VALUE_OPTIONAL, ++ 'Key has to be a 32 characters long string. If not provided, a random key will be generated.' ++ ); ++ ++ parent::configure(); ++ } ++ ++ /** ++ * @inheritDoc ++ */ ++ protected function execute(InputInterface $input, OutputInterface $output) ++ { ++ try { ++ $key = $input->getOption('key'); ++ ++ if (!empty($key)) { ++ $this->encryptor->validateKey($key); ++ } ++ ++ $this->updateEncryptionKey($key); ++ $this->cache->clean(); ++ ++ $output->writeln('Encryption key has been updated successfully.'); ++ ++ return Cli::RETURN_SUCCESS; ++ } catch (\Exception $e) { ++ $output->writeln('' . $e->getMessage() . ''); ++ return Cli::RETURN_FAILURE; ++ } ++ } ++ ++ /** ++ * Update encryption key ++ * ++ * @param string|null $key ++ * @return void ++ * @throws FileSystemException ++ */ ++ private function updateEncryptionKey(string $key = null): void ++ { ++ // prepare new key, encryptor and new configuration segment ++ if (!$this->writer->checkIfWritable()) { ++ throw new FileSystemException(__('Deployment configuration file is not writable.')); ++ } ++ ++ if (null === $key) { ++ // md5() here is not for cryptographic use. It used for generate encryption key itself ++ // and do not encrypt any passwords ++ // phpcs:ignore Magento2.Security.InsecureFunction ++ $key = md5($this->random->getRandomString(ConfigOptionsListConstants::STORE_KEY_RANDOM_STRING_SIZE)); ++ } ++ $this->encryptor->setNewKey($key); ++ ++ $encryptSegment = new ConfigData(ConfigFilePool::APP_ENV); ++ $encryptSegment->set(ConfigOptionsListConstants::CONFIG_PATH_CRYPT_KEY, $this->encryptor->exportKeys()); ++ ++ $configData = [$encryptSegment->getFileKey() => $encryptSegment->getData()]; ++ ++ $this->writer->saveConfig($configData); ++ } ++} +diff --git a/vendor/magento/module-encryption-key/etc/di.xml b/vendor/magento/module-encryption-key/etc/di.xml +index b4e471f4e40ef..495234759a7f8 100644 +--- a/vendor/magento/module-encryption-key/etc/di.xml ++++ b/vendor/magento/module-encryption-key/etc/di.xml +@@ -11,4 +11,11 @@ + Magento\Config\Model\Config\Structure\Proxy + + ++ ++ ++ ++ Magento\EncryptionKey\Console\Command\UpdateEncryptionKeyCommand ++ ++ ++ + diff --git a/patches/MCLOUD-12969__Patch_for_CVE_2024_34102_KeyRotation__2.4.6.patch b/patches/MCLOUD-12969__Patch_for_CVE_2024_34102_KeyRotation__2.4.6.patch new file mode 100644 index 0000000..c5ba438 --- /dev/null +++ b/patches/MCLOUD-12969__Patch_for_CVE_2024_34102_KeyRotation__2.4.6.patch @@ -0,0 +1,159 @@ +diff --git a/vendor/magento/module-encryption-key/Console/Command/UpdateEncryptionKeyCommand.php b/vendor/magento/module-encryption-key/Console/Command/UpdateEncryptionKeyCommand.php +new file mode 100644 +index 0000000000000..0e4995b847893 +--- /dev/null ++++ b/vendor/magento/module-encryption-key/Console/Command/UpdateEncryptionKeyCommand.php +@@ -0,0 +1,137 @@ ++encryptor = $encryptor; ++ $this->cache = $cache; ++ $this->writer = $writer; ++ $this->random = $random; ++ ++ parent::__construct(); ++ } ++ ++ /** ++ * @inheritDoc ++ */ ++ protected function configure() ++ { ++ $this->setName('encryption:key:change'); ++ $this->setDescription('Change the encryption key inside the env.php file.'); ++ $this->addOption( ++ 'key', ++ 'k', ++ InputOption::VALUE_OPTIONAL, ++ 'Key has to be a 32 characters long string. If not provided, a random key will be generated.' ++ ); ++ ++ parent::configure(); ++ } ++ ++ /** ++ * @inheritDoc ++ */ ++ protected function execute(InputInterface $input, OutputInterface $output) ++ { ++ try { ++ $key = $input->getOption('key'); ++ ++ if (!empty($key)) { ++ $this->encryptor->validateKey($key); ++ } ++ ++ $this->updateEncryptionKey($key); ++ $this->cache->clean(); ++ ++ $output->writeln('Encryption key has been updated successfully.'); ++ ++ return Command::SUCCESS; ++ } catch (\Exception $e) { ++ $output->writeln('' . $e->getMessage() . ''); ++ return Command::FAILURE; ++ } ++ } ++ ++ /** ++ * Update encryption key ++ * ++ * @param string|null $key ++ * @return void ++ * @throws FileSystemException ++ */ ++ private function updateEncryptionKey(string $key = null): void ++ { ++ // prepare new key, encryptor and new configuration segment ++ if (!$this->writer->checkIfWritable()) { ++ throw new FileSystemException(__('Deployment configuration file is not writable.')); ++ } ++ ++ if (null === $key) { ++ // md5() here is not for cryptographic use. It used for generate encryption key itself ++ // and do not encrypt any passwords ++ // phpcs:ignore Magento2.Security.InsecureFunction ++ $key = md5($this->random->getRandomString(ConfigOptionsListConstants::STORE_KEY_RANDOM_STRING_SIZE)); ++ } ++ ++ $this->encryptor->setNewKey($key); ++ ++ $encryptSegment = new ConfigData(ConfigFilePool::APP_ENV); ++ $encryptSegment->set(ConfigOptionsListConstants::CONFIG_PATH_CRYPT_KEY, $this->encryptor->exportKeys()); ++ ++ $configData = [$encryptSegment->getFileKey() => $encryptSegment->getData()]; ++ ++ $this->writer->saveConfig($configData); ++ } ++} +diff --git a/vendor/magento/module-encryption-key/etc/di.xml b/vendor/magento/module-encryption-key/etc/di.xml +index b4e471f4e40ef..495234759a7f8 100644 +--- a/vendor/magento/module-encryption-key/etc/di.xml ++++ b/vendor/magento/module-encryption-key/etc/di.xml +@@ -11,4 +11,11 @@ + Magento\Config\Model\Config\Structure\Proxy + + ++ ++ ++ ++ Magento\EncryptionKey\Console\Command\UpdateEncryptionKeyCommand ++ ++ ++ + diff --git a/patches/MCLOUD-12969__Patch_for_CVE_2024_34102_KeyRotation__2.4.7.patch b/patches/MCLOUD-12969__Patch_for_CVE_2024_34102_KeyRotation__2.4.7.patch new file mode 100644 index 0000000..0c8e1fc --- /dev/null +++ b/patches/MCLOUD-12969__Patch_for_CVE_2024_34102_KeyRotation__2.4.7.patch @@ -0,0 +1,157 @@ +diff --git a/vendor/magento/module-encryption-key/Console/Command/UpdateEncryptionKeyCommand.php b/vendor/magento/module-encryption-key/Console/Command/UpdateEncryptionKeyCommand.php +new file mode 100644 +index 0000000000000..cd6ffb4323163 +--- /dev/null ++++ b/vendor/magento/module-encryption-key/Console/Command/UpdateEncryptionKeyCommand.php +@@ -0,0 +1,135 @@ ++encryptor = $encryptor; ++ $this->cache = $cache; ++ $this->writer = $writer; ++ $this->random = $random; ++ ++ parent::__construct(); ++ } ++ ++ /** ++ * @inheritDoc ++ */ ++ protected function configure() ++ { ++ $this->setName('encryption:key:change'); ++ $this->setDescription('Change the encryption key inside the env.php file.'); ++ $this->addOption( ++ 'key', ++ 'k', ++ InputOption::VALUE_OPTIONAL, ++ 'Key has to be a 32 characters long string. If not provided, a random key will be generated.' ++ ); ++ ++ parent::configure(); ++ } ++ ++ /** ++ * @inheritDoc ++ */ ++ protected function execute(InputInterface $input, OutputInterface $output) ++ { ++ try { ++ $key = $input->getOption('key'); ++ ++ if (!empty($key)) { ++ $this->encryptor->validateKey($key); ++ } ++ ++ $this->updateEncryptionKey($key); ++ $this->cache->clean(); ++ ++ $output->writeln('Encryption key has been updated successfully.'); ++ ++ return Command::SUCCESS; ++ } catch (\Exception $e) { ++ $output->writeln('' . $e->getMessage() . ''); ++ return Command::FAILURE; ++ } ++ } ++ ++ /** ++ * Update encryption key ++ * ++ * @param string|null $key ++ * @return void ++ * @throws FileSystemException ++ */ ++ private function updateEncryptionKey(string $key = null): void ++ { ++ // prepare new key, encryptor and new configuration segment ++ if (!$this->writer->checkIfWritable()) { ++ throw new FileSystemException(__('Deployment configuration file is not writable.')); ++ } ++ ++ if (null === $key) { ++ $key = ConfigOptionsListConstants::STORE_KEY_ENCODED_RANDOM_STRING_PREFIX . ++ $this->random->getRandomBytes(ConfigOptionsListConstants::STORE_KEY_RANDOM_STRING_SIZE); ++ } ++ ++ $this->encryptor->setNewKey($key); ++ ++ $encryptSegment = new ConfigData(ConfigFilePool::APP_ENV); ++ $encryptSegment->set(ConfigOptionsListConstants::CONFIG_PATH_CRYPT_KEY, $this->encryptor->exportKeys()); ++ ++ $configData = [$encryptSegment->getFileKey() => $encryptSegment->getData()]; ++ ++ $this->writer->saveConfig($configData); ++ } ++} +diff --git a/vendor/magento/module-encryption-key/etc/di.xml b/vendor/magento/module-encryption-key/etc/di.xml +index b4e471f4e40ef..495234759a7f8 100644 +--- a/vendor/magento/module-encryption-key/etc/di.xml ++++ b/vendor/magento/module-encryption-key/etc/di.xml +@@ -11,4 +11,11 @@ + Magento\Config\Model\Config\Structure\Proxy + + ++ ++ ++ ++ Magento\EncryptionKey\Console\Command\UpdateEncryptionKeyCommand ++ ++ ++ +