From 2a2a2fb504247e8966f8ffc2e17d614be5d43128 Mon Sep 17 00:00:00 2001 From: Colin Mollenhour Date: Tue, 29 Aug 2023 11:35:03 -0400 Subject: [PATCH] Merge pull request from GHSA-9358-cpvx-c2qp Co-authored-by: Fabrizio Balliano --- app/code/core/Mage/Core/Helper/Data.php | 35 +++++++++++++ app/code/core/Mage/Core/etc/config.xml | 4 ++ app/code/core/Mage/Core/etc/system.xml | 63 ++++++++++------------- app/code/core/Mage/Sales/Helper/Guest.php | 6 ++- app/code/core/Mage/Sales/Model/Order.php | 2 +- app/locale/en_US/Mage_Core.csv | 1 + 6 files changed, 73 insertions(+), 38 deletions(-) diff --git a/app/code/core/Mage/Core/Helper/Data.php b/app/code/core/Mage/Core/Helper/Data.php index 2d1043a8dd2..d9955c26c7f 100644 --- a/app/code/core/Mage/Core/Helper/Data.php +++ b/app/code/core/Mage/Core/Helper/Data.php @@ -1000,4 +1000,39 @@ public function unEscapeCSVData($data) } 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')); + } + } } diff --git a/app/code/core/Mage/Core/etc/config.xml b/app/code/core/Mage/Core/etc/config.xml index ef593b10ba2..d7ce041219d 100644 --- a/app/code/core/Mage/Core/etc/config.xml +++ b/app/code/core/Mage/Core/etc/config.xml @@ -315,6 +315,10 @@ 1 + + 1 + 30 + 30 2 * * * diff --git a/app/code/core/Mage/Core/etc/system.xml b/app/code/core/Mage/Core/etc/system.xml index 9864433dedb..489b1e6fcf2 100644 --- a/app/code/core/Mage/Core/etc/system.xml +++ b/app/code/core/Mage/Core/etc/system.xml @@ -50,6 +50,33 @@ + + + 10 + 1 + 1 + 1 + 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. + + + + select + adminhtml/system_config_source_yesno + 10 + 1 + 1 + 1 + + + + 20 + 1 + 1 + 1 + Number of seconds between each allowed request. + + + 1000 @@ -69,13 +96,6 @@ - advanced @@ -84,35 +104,6 @@ 1 1 - adminhtml/system_config_form_fieldset_modules_disableOutput diff --git a/app/code/core/Mage/Sales/Helper/Guest.php b/app/code/core/Mage/Sales/Helper/Guest.php index cbb841b5a5b..9d6099d9304 100644 --- a/app/code/core/Mage/Sales/Helper/Guest.php +++ b/app/code/core/Mage/Sales/Helper/Guest.php @@ -105,6 +105,7 @@ public function loadValidOrder() $errors = true; } } else { + Mage::helper('core')->recordRateLimitHit(); $errors = true; } } @@ -114,7 +115,10 @@ public function loadValidOrder() 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; } diff --git a/app/code/core/Mage/Sales/Model/Order.php b/app/code/core/Mage/Sales/Model/Order.php index ef55f66da25..ec00ea9bd88 100644 --- a/app/code/core/Mage/Sales/Model/Order.php +++ b/app/code/core/Mage/Sales/Model/Order.php @@ -2372,7 +2372,7 @@ protected function _beforeSave() } 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')) { diff --git a/app/locale/en_US/Mage_Core.csv b/app/locale/en_US/Mage_Core.csv index 4322d2f9f70..91b9d95fadb 100644 --- a/app/locale/en_US/Mage_Core.csv +++ b/app/locale/en_US/Mage_Core.csv @@ -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."