CVE-2023-41879 (published 2023-09-11T22:15Z)

Magento LTS is the official OpenMage LTS codebase. Guest orders may be viewed without authentication using a "guest-view" cookie which contains the order\'s "protect_code". This code is 6 hexadecimal characters which is arguably not enough to prevent a brute-force attack. Exposing each order would require a separate brute force attack. This issue has been patched in versions 19.5.1 and 20.1.1.

CVSS v3 base score: 7.5, HIGH (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N)

Weakness information:
cwe_id: CWE-330
cwe_name: Use of Insufficiently Random Values
description: The product uses insufficiently random numbers or values in a security context that depends on unpredictable numbers.
extended_description: When product generates predictable values in a context requiring unpredictability, it may be possible for an attacker to guess the next value that will be generated, and use this guess to impersonate another user or access sensitive information.
         

Fix information:
repo_url: https://github.com/OpenMage/magento-lts
commit_details: repo_url: https://github.com/OpenMage/magento-lts
author: Colin Mollenhour
author_date: 2023-08-29 11:35:03-04:00
msg: Merge pull request from GHSA-9358-cpvx-c2qp

Co-authored-by: Fabrizio Balliano <fabrizio.balliano@gmail.com>
repository: repo_url: https://github.com/OpenMage/magento-lts
repo_name: OpenMage/magento-lts
description: Official OpenMage LTS codebase | Migrate easily from Magento Community Edition in minutes! Download the source code for free or contribute to OpenMage LTS | Security vulnerability patches, bug fixes, performance improvements and more.
repo_language: PHP
owner: OpenMage
file_changes: filename: Data.php
change_type: ModificationType.MODIFY
diff: @@ -1000,4 +1000,39 @@ XML;
         }
         return $data;
     }
+
+    /**
+     * @param bool $setErrorMessage Adds a predefined error message to the 'core/session' object
+     * @return bool
+     */
+    public function isRateLimitExceeded($setErrorMessage = true, $recordRateLimitHit = true): bool
+    {
+        $active = Mage::getStoreConfigFlag('system/rate_limit/active');
+        if ($active && $remoteAddr = Mage::helper('core/http')->getRemoteAddr()) {
+            $cacheTag = 'rate_limit_' . $remoteAddr;
+            if (Mage::app()->testCache($cacheTag)) {
+                $errorMessage = "Too Soon: You are trying to perform this operation too frequently. Please wait a few seconds and try again.";
+                Mage::getSingleton('core/session')->addError($this->__($errorMessage));
+                return true;
+            }
+
+            if ($recordRateLimitHit) {
+                $this->recordRateLimitHit();
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * @return void
+     */
+    public function recordRateLimitHit(): void
+    {
+        $active = Mage::getStoreConfigFlag('system/rate_limit/active');
+        if ($active && $remoteAddr = Mage::helper('core/http')->getRemoteAddr()) {
+            $cacheTag = 'rate_limit_' . $remoteAddr;
+            Mage::app()->saveCache(1, $cacheTag, ['brute_force'], Mage::getStoreConfig('system/rate_limit/timeframe'));
+        }
+    }
 }

programming_language: PHP
filename: config.xml
change_type: ModificationType.MODIFY
diff: @@ -315,6 +315,10 @@
             <csrf>
                 <use_form_key>1</use_form_key>
             </csrf>
+            <rate_limit>
+                <active>1</active>
+                <timeframe>30</timeframe>
+            </rate_limit>
             <cache>
                 <flush_cron_expr>30 2 * * *</flush_cron_expr>
             </cache>

programming_language: HTML
filename: system.xml
change_type: ModificationType.MODIFY
diff: @@ -50,6 +50,33 @@
                         </use_form_key>
                     </fields>
                 </csrf>
+                <rate_limit translate="label comment" module="core">
+                    <label>Rate limit</label>
+                    <sort_order>10</sort_order>
+                    <show_in_default>1</show_in_default>
+                    <show_in_website>1</show_in_website>
+                    <show_in_store>1</show_in_store>
+                    <comment>This functionality limits the number of requests a user (identified by IP address) can perform within a specific time frame, preventing excessive resources usage and maintaining system performance, stability and security.</comment>
+                    <fields>
+                        <active translate="label">
+                            <label>Enabled</label>
+                            <frontend_type>select</frontend_type>
+                            <source_model>adminhtml/system_config_source_yesno</source_model>
+                            <sort_order>10</sort_order>
+                            <show_in_default>1</show_in_default>
+                            <show_in_website>1</show_in_website>
+                            <show_in_store>1</show_in_store>
+                        </active>
+                        <timeframe translate="label comment">
+                            <label>Timeframe</label>
+                            <sort_order>20</sort_order>
+                            <show_in_default>1</show_in_default>
+                            <show_in_website>1</show_in_website>
+                            <show_in_store>1</show_in_store>
+                            <comment>Number of seconds between each allowed request.</comment>
+                        </timeframe>
+                    </fields>
+                </rate_limit>
                 <cache translate="label" module="core">
                     <label>Advanced Cache Settings</label>
                     <sort_order>1000</sort_order>
@@ -69,13 +96,6 @@
                 </cache>
             </groups>
         </system>
-        <!--<web_track translate="label" module="core">
-            <label>Web Tracking</label>
-            <sort_order>180</sort_order>
-            <show_in_default>1</show_in_default>
-            <show_in_website>1</show_in_website>
-            <show_in_store>1</show_in_store>
-        </web_track>-->
         <advanced translate="label" module="core">
             <label>Advanced</label>
             <tab>advanced</tab>
@@ -84,35 +104,6 @@
             <show_in_website>1</show_in_website>
             <show_in_store>1</show_in_store>
             <groups>
-                <!--datashare translate="label">
-                    <label>Datasharing</label>
-                    <sort_order>1</sort_order>
-                    <show_in_default>1</show_in_default>
-                    <show_in_website>1</show_in_website>
-                    <show_in_store>0</show_in_store>
-                    <fields>
-                        <default translate="label">
-                            <label>Default</label>
-                            <frontend_type>multiselect</frontend_type>
-                            <backend_model>adminhtml/system_config_backend_datashare</backend_model>
-                            <source_model>adminhtml/system_config_source_store</source_model>
-                            <sort_order>1</sort_order>
-                            <show_in_default>1</show_in_default>
-                            <show_in_website>1</show_in_website>
-                            <show_in_store>1</show_in_store>
-                        </default>
-                        <default translate="label">
-                            <label>Default</label>
-                            <frontend_type>multiselect</frontend_type>
-                            <backend_model>adminhtml/system_config_backend_datashare</backend_model>
-                            <source_model>adminhtml/system_config_source_store</source_model>
-                            <sort_order>1</sort_order>
-                            <show_in_default>1</show_in_default>
-                            <show_in_website>1</show_in_website>
-                            <show_in_store>1</show_in_store>
-                        </default>
-                    </fields>
-                </datashare-->
                 <modules_disable_output translate="label">
                     <label>Disable Modules Output</label>
                     <frontend_model>adminhtml/system_config_form_fieldset_modules_disableOutput</frontend_model>

programming_language: HTML
filename: Guest.php
change_type: ModificationType.MODIFY
diff: @@ -105,6 +105,7 @@ class Mage_Sales_Helper_Guest extends Mage_Core_Helper_Data
                     $errors = true;
                 }
             } else {
+                Mage::helper('core')->recordRateLimitHit();
                 $errors = true;
             }
         }
@@ -114,7 +115,10 @@ class Mage_Sales_Helper_Guest extends Mage_Core_Helper_Data
             return true;
         }
 
-        Mage::getSingleton('core/session')->addError($this->__($errorMessage));
+        if (!Mage::helper('core')->isRateLimitExceeded(true, false)) {
+            Mage::getSingleton('core/session')->addError($this->__($errorMessage));
+        }
+
         Mage::app()->getResponse()->setRedirect(Mage::getUrl('sales/guest/form'));
         return false;
     }

programming_language: PHP
filename: Order.php
change_type: ModificationType.MODIFY
diff: @@ -2372,7 +2372,7 @@ class Mage_Sales_Model_Order extends Mage_Sales_Model_Abstract
         }
 
         if (!$this->getId()) {
-            $this->setData('protect_code', substr(md5(uniqid(mt_rand(), true) . ':' . microtime(true)), 5, 6));
+            $this->setData('protect_code', Mage::helper('core')->getRandomString(16));
         }
 
         if ($this->getStatus() !== $this->getOrigData('status')) {

programming_language: PHP
filename: Mage_Core.csv
change_type: ModificationType.MODIFY
diff: @@ -384,6 +384,7 @@
 "Timezone","Timezone"
 "Title Prefix","Title Prefix"
 "Title Suffix","Title Suffix"
+"Too Soon: You are trying to perform this operation too frequently. Please wait a few seconds and try again.","Too Soon: You are trying to perform this operation too frequently. Please wait a few seconds and try again."
 "Transactional Emails","Transactional Emails"
 "Translate Inline","Translate Inline"
 "Translate, blocks and other output caches should be disabled for both frontend and admin inline translations.","Translate, blocks and other output caches should be disabled for both frontend and admin inline translations."

programming_language: Haskell