From 6a14d9460cc9b4cf25a5fd53f4d115fb9ad71d36 Mon Sep 17 00:00:00 2001 From: Michael Furtner Date: Thu, 22 Jun 2017 17:47:18 +0200 Subject: [PATCH 1/4] Update Magento 1.8.1.0 with SUPEE-8167 --- app/code/core/Mage/Paypal/Model/Ipn.php | 30 +++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/app/code/core/Mage/Paypal/Model/Ipn.php b/app/code/core/Mage/Paypal/Model/Ipn.php index b4e794d157e..f6e85beee69 100644 --- a/app/code/core/Mage/Paypal/Model/Ipn.php +++ b/app/code/core/Mage/Paypal/Model/Ipn.php @@ -36,6 +36,20 @@ class Mage_Paypal_Model_Ipn */ const DEFAULT_LOG_FILE = 'paypal_unknown_ipn.log'; + /** + * Default postback endpoint URL. + * + * @var string + */ + const DEFAULT_POSTBACK_URL = 'https://ipnpb.paypal.com/cgi-bin/webscr'; + + /** + * Sandbox postback endpoint URL. + * + * @var string + */ + const SANDBOX_POSTBACK_URL = 'https://ipnpb.sandbox.paypal.com/cgi-bin/webscr'; + /* * @param Mage_Sales_Model_Order */ @@ -130,6 +144,8 @@ public function processIpnRequest(array $request, Zend_Http_Client_Adapter_Inter */ protected function _postBack(Zend_Http_Client_Adapter_Interface $httpAdapter) { + $url = $this->_getPostbackUrl(); + $sReq = ''; foreach ($this->_request as $k => $v) { $sReq .= '&'.$k.'='.urlencode($v); @@ -137,10 +153,10 @@ protected function _postBack(Zend_Http_Client_Adapter_Interface $httpAdapter) $sReq .= "&cmd=_notify-validate"; $sReq = substr($sReq, 1); $this->_debugData['postback'] = $sReq; - $this->_debugData['postback_to'] = $this->_config->getPaypalUrl(); + $this->_debugData['postback_to'] = $url; $httpAdapter->setConfig(array('verifypeer' => $this->_config->verifyPeer)); - $httpAdapter->write(Zend_Http_Client::POST, $this->_config->getPaypalUrl(), '1.1', array( + $httpAdapter->write(Zend_Http_Client::POST, $url, '1.1', array( 'Connection: close', ), $sReq); try { @@ -159,6 +175,16 @@ protected function _postBack(Zend_Http_Client_Adapter_Interface $httpAdapter) unset($this->_debugData['postback'], $this->_debugData['postback_result']); } + /** + * Get postback endpoint URL. + * + * @return string + */ + protected function _getPostbackUrl() + { + return $this->_config->sandboxFlag ? self::SANDBOX_POSTBACK_URL : self::DEFAULT_POSTBACK_URL; + } + /** * Load and validate order, instantiate proper configuration * From d310f8271140d4ac23e4717cf5fb407c5a03f924 Mon Sep 17 00:00:00 2001 From: Leo Friedrichs Date: Fri, 30 Jun 2017 10:09:36 +0200 Subject: [PATCH 2/4] Apply patch SUPEE-8967 --- app/code/core/Mage/Payment/Model/Method/Cc.php | 2 +- app/etc/applied.patches.list | 5 +++++ js/prototype/validation.js | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/app/code/core/Mage/Payment/Model/Method/Cc.php b/app/code/core/Mage/Payment/Model/Method/Cc.php index ccf240ee344..7b6f3b92d42 100644 --- a/app/code/core/Mage/Payment/Model/Method/Cc.php +++ b/app/code/core/Mage/Payment/Model/Method/Cc.php @@ -123,7 +123,7 @@ public function validate() // Visa 'VI' => '/^4[0-9]{12}([0-9]{3})?$/', // Master Card - 'MC' => '/^5[1-5][0-9]{14}$/', + 'MC' => '/^(5[1-5][0-9]{14}|2(22[1-9][0-9]{12}|2[3-9][0-9]{13}|[3-6][0-9]{14}|7[0-1][0-9]{13}|720[0-9]{12}))$/', // American Express 'AE' => '/^3[47][0-9]{13}$/', // Discovery diff --git a/app/etc/applied.patches.list b/app/etc/applied.patches.list index b21bd43b60a..45e9ad20e7f 100644 --- a/app/etc/applied.patches.list +++ b/app/etc/applied.patches.list @@ -356,3 +356,8 @@ patching file skin/adminhtml/default/default/media/uploaderSingle.swf patching file skin/adminhtml/default/default/xmlconnect/boxes.css +2017-06-30 08:09:15 UTC | SUPEE-8967 | EE_1.13.1.0 | v1 | 1fa53e9533f6f3a16f24d9b64dabef0ab7f965d7 | Thu Aug 18 16:32:48 2016 +0300 | 97d160644..1fa53e9533 +patching file app/code/core/Mage/Payment/Model/Method/Cc.php +patching file js/prototype/validation.js + + diff --git a/js/prototype/validation.js b/js/prototype/validation.js index c9c17988033..ef9308c3256 100644 --- a/js/prototype/validation.js +++ b/js/prototype/validation.js @@ -881,7 +881,7 @@ Validation.creditCartTypes = $H({ 'SO': [new RegExp('^(6334[5-9]([0-9]{11}|[0-9]{13,14}))|(6767([0-9]{12}|[0-9]{14,15}))$'), new RegExp('^([0-9]{3}|[0-9]{4})?$'), true], 'SM': [new RegExp('(^(5[0678])[0-9]{11,18}$)|(^(6[^05])[0-9]{11,18}$)|(^(601)[^1][0-9]{9,16}$)|(^(6011)[0-9]{9,11}$)|(^(6011)[0-9]{13,16}$)|(^(65)[0-9]{11,13}$)|(^(65)[0-9]{15,18}$)|(^(49030)[2-9]([0-9]{10}$|[0-9]{12,13}$))|(^(49033)[5-9]([0-9]{10}$|[0-9]{12,13}$))|(^(49110)[1-2]([0-9]{10}$|[0-9]{12,13}$))|(^(49117)[4-9]([0-9]{10}$|[0-9]{12,13}$))|(^(49118)[0-2]([0-9]{10}$|[0-9]{12,13}$))|(^(4936)([0-9]{12}$|[0-9]{14,15}$))'), new RegExp('^([0-9]{3}|[0-9]{4})?$'), true], 'VI': [new RegExp('^4[0-9]{12}([0-9]{3})?$'), new RegExp('^[0-9]{3}$'), true], - 'MC': [new RegExp('^5[1-5][0-9]{14}$'), new RegExp('^[0-9]{3}$'), true], + 'MC': [new RegExp('^(5[1-5][0-9]{14}|2(22[1-9][0-9]{12}|2[3-9][0-9]{13}|[3-6][0-9]{14}|7[0-1][0-9]{13}|720[0-9]{12}))$'), new RegExp('^[0-9]{3}$'), true], 'AE': [new RegExp('^3[47][0-9]{13}$'), new RegExp('^[0-9]{4}$'), true], 'DI': [new RegExp('^6011[0-9]{12}$'), new RegExp('^[0-9]{3}$'), true], 'JCB': [new RegExp('^(3[0-9]{15}|(2131|1800)[0-9]{11})$'), new RegExp('^[0-9]{3,4}$'), true], From d915866bfe75aed4f3fa6a0ab75711efd1a231d2 Mon Sep 17 00:00:00 2001 From: Leo Friedrichs Date: Fri, 30 Jun 2017 10:10:04 +0200 Subject: [PATCH 3/4] Apply patch SUPEE-9652 --- app/etc/applied.patches.list | 4 ++++ lib/Zend/Mail/Transport/Sendmail.php | 21 +++++++++++++-------- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/app/etc/applied.patches.list b/app/etc/applied.patches.list index 45e9ad20e7f..8884eabd6f3 100644 --- a/app/etc/applied.patches.list +++ b/app/etc/applied.patches.list @@ -361,3 +361,7 @@ patching file app/code/core/Mage/Payment/Model/Method/Cc.php patching file js/prototype/validation.js +2017-06-30 08:09:45 UTC | SUPEE-9652 | EE_1.14.3.1 | v1 | 4038f0785d828794083f53f10c01aaa6af403523 | Tue Jan 24 15:03:12 2017 +0200 | 9586981e6ca8b255014b242d50b68b88525b0754..4038f0785d828794083f53f10c01aaa6af403523 +patching file lib/Zend/Mail/Transport/Sendmail.php + + diff --git a/lib/Zend/Mail/Transport/Sendmail.php b/lib/Zend/Mail/Transport/Sendmail.php index d2c010b1bac..b27f81dfde0 100644 --- a/lib/Zend/Mail/Transport/Sendmail.php +++ b/lib/Zend/Mail/Transport/Sendmail.php @@ -119,14 +119,19 @@ public function _sendMail() ); } - set_error_handler(array($this, '_handleMailErrors')); - $result = mail( - $this->recipients, - $this->_mail->getSubject(), - $this->body, - $this->header, - $this->parameters); - restore_error_handler(); + // Sanitize the From header + if (!Zend_Validate::is(str_replace(' ', '', $this->parameters), 'EmailAddress')) { + throw new Zend_Mail_Transport_Exception('Potential code injection in From header'); + } else { + set_error_handler(array($this, '_handleMailErrors')); + $result = mail( + $this->recipients, + $this->_mail->getSubject(), + $this->body, + $this->header, + $this->parameters); + restore_error_handler(); + } } if ($this->_errstr !== null || !$result) { From 285abc2b984535344a226df622c9ae52c53490c5 Mon Sep 17 00:00:00 2001 From: Leo Friedrichs Date: Fri, 30 Jun 2017 10:10:40 +0200 Subject: [PATCH 4/4] Apply patch SUPEE-9767 --- app/code/core/Mage/Admin/Model/Session.php | 3 + .../Mage/Adminhtml/Block/Checkout/Formkey.php | 52 ++++++++++++++++++ .../Adminhtml/Block/Notification/Symlink.php | 36 ++++++++++++ .../Block/Widget/Grid/Column/Filter/Date.php | 4 +- .../core/Mage/Adminhtml/Model/Config/Data.php | 3 + .../Backend/Web/Secure/Offloaderheader.php | 29 ++++++++++ .../Catalog/Product/GalleryController.php | 5 ++ .../controllers/MultishippingController.php | 16 ++++++ .../controllers/OnepageController.php | 25 +++++++++ app/code/core/Mage/Checkout/etc/system.xml | 18 ++++++ .../Mage/Cms/Model/Wysiwyg/Images/Storage.php | 5 ++ .../Mage/Core/Controller/Front/Action.php | 39 +++++++++++++ .../Mage/Core/Controller/Request/Http.php | 5 +- .../Mage/Core/Model/File/Validator/Image.php | 32 +++++++++-- app/code/core/Mage/Core/etc/config.xml | 3 + app/code/core/Mage/Core/etc/system.xml | 40 +++++++------- app/code/core/Mage/Customer/Model/Session.php | 3 + .../Model/Convert/Adapter/Zend/Cache.php | 3 + .../Model/Convert/Container/Abstract.php | 55 +++++++++++++++++-- .../Dataflow/Model/Convert/Parser/Csv.php | 10 ++-- .../Model/Convert/Parser/Xml/Excel.php | 7 ++- .../ImportExport/Model/Import/Uploader.php | 5 ++ app/code/core/Mage/Sales/Model/Quote/Item.php | 5 +- app/code/core/Mage/Tax/Model/Calculation.php | 11 ++++ .../Mage/Tax/Model/Resource/Calculation.php | 29 ++++++++++ .../Mage/Widget/Model/Widget/Instance.php | 6 +- .../core/Mage/XmlConnect/Helper/Image.php | 5 ++ .../Adminhtml/MobileController.php | 7 ++- .../adminhtml/default/default/layout/main.xml | 3 +- .../template/notification/formkey.phtml | 38 +++++++++++++ .../template/notification/symlink.phtml | 34 ++++++++++++ .../default/default/template/page/head.phtml | 2 +- .../template/checkout/cart/shipping.phtml | 1 + .../checkout/multishipping/billing.phtml | 1 + .../checkout/multishipping/shipping.phtml | 1 + .../template/checkout/onepage/billing.phtml | 1 + .../template/checkout/onepage/payment.phtml | 1 + .../template/checkout/onepage/shipping.phtml | 1 + .../checkout/onepage/shipping_method.phtml | 1 + .../persistent/checkout/onepage/billing.phtml | 1 + app/etc/applied.patches.list | 52 ++++++++++++++++++ app/locale/en_US/Mage_Adminhtml.csv | 2 + app/locale/en_US/Mage_Core.csv | 1 + app/locale/en_US/Mage_Dataflow.csv | 1 + app/locale/en_US/Mage_XmlConnect.csv | 2 +- downloader/Maged/Connect.php | 7 ++- downloader/Maged/Controller.php | 39 ++++++++----- downloader/Maged/Model/Session.php | 34 ++++++++++++ js/varien/payment.js | 2 +- skin/frontend/base/default/js/opcheckout.js | 2 +- 50 files changed, 624 insertions(+), 64 deletions(-) create mode 100644 app/code/core/Mage/Adminhtml/Block/Checkout/Formkey.php create mode 100644 app/code/core/Mage/Adminhtml/Block/Notification/Symlink.php create mode 100644 app/code/core/Mage/Adminhtml/Model/System/Config/Backend/Web/Secure/Offloaderheader.php create mode 100644 app/design/adminhtml/default/default/template/notification/formkey.phtml create mode 100644 app/design/adminhtml/default/default/template/notification/symlink.phtml mode change 100755 => 100644 downloader/Maged/Controller.php diff --git a/app/code/core/Mage/Admin/Model/Session.php b/app/code/core/Mage/Admin/Model/Session.php index 6e414768cb8..40641d286bb 100644 --- a/app/code/core/Mage/Admin/Model/Session.php +++ b/app/code/core/Mage/Admin/Model/Session.php @@ -138,6 +138,9 @@ public function login($username, $password, $request = null) Mage::throwException(Mage::helper('adminhtml')->__('Invalid User Name or Password.')); } } catch (Mage_Core_Exception $e) { + $e->setMessage( + Mage::helper('adminhtml')->__('You did not sign in correctly or your account is temporarily disabled.') + ); Mage::dispatchEvent('admin_session_user_login_failed', array('user_name' => $username, 'exception' => $e)); if ($request && !$request->getParam('messageSent')) { diff --git a/app/code/core/Mage/Adminhtml/Block/Checkout/Formkey.php b/app/code/core/Mage/Adminhtml/Block/Checkout/Formkey.php new file mode 100644 index 00000000000..fb564d24919 --- /dev/null +++ b/app/code/core/Mage/Adminhtml/Block/Checkout/Formkey.php @@ -0,0 +1,52 @@ + Admin section + * + * @return string + */ + public function getSecurityAdminUrl() + { + return Mage::helper("adminhtml")->getUrl('adminhtml/system_config/edit/section/admin'); + } +} diff --git a/app/code/core/Mage/Adminhtml/Block/Notification/Symlink.php b/app/code/core/Mage/Adminhtml/Block/Notification/Symlink.php new file mode 100644 index 00000000000..9e8759096ae --- /dev/null +++ b/app/code/core/Mage/Adminhtml/Block/Notification/Symlink.php @@ -0,0 +1,36 @@ +_convertDate($value['from'], $value['locale']); + $value['from'] = $this->_convertDate($this->stripTags($value['from']), $value['locale']); } if (!empty($value['to'])) { $value['orig_to'] = $value['to']; - $value['to'] = $this->_convertDate($value['to'], $value['locale']); + $value['to'] = $this->_convertDate($this->stripTags($value['to']), $value['locale']); } } if (empty($value['from']) && empty($value['to'])) { diff --git a/app/code/core/Mage/Adminhtml/Model/Config/Data.php b/app/code/core/Mage/Adminhtml/Model/Config/Data.php index 437e257bb60..f1d066ae35b 100644 --- a/app/code/core/Mage/Adminhtml/Model/Config/Data.php +++ b/app/code/core/Mage/Adminhtml/Model/Config/Data.php @@ -167,6 +167,9 @@ public function save() if (is_object($fieldConfig)) { $configPath = (string)$fieldConfig->config_path; if (!empty($configPath) && strrpos($configPath, '/') > 0) { + if (!Mage::getSingleton('admin/session')->isAllowed($configPath)) { + Mage::throwException('Access denied.'); + } // Extend old data with specified section group $groupPath = substr($configPath, 0, strrpos($configPath, '/')); if (!isset($oldConfigAdditionalGroups[$groupPath])) { diff --git a/app/code/core/Mage/Adminhtml/Model/System/Config/Backend/Web/Secure/Offloaderheader.php b/app/code/core/Mage/Adminhtml/Model/System/Config/Backend/Web/Secure/Offloaderheader.php new file mode 100644 index 00000000000..4f58256f574 --- /dev/null +++ b/app/code/core/Mage/Adminhtml/Model/System/Config/Backend/Web/Secure/Offloaderheader.php @@ -0,0 +1,29 @@ +setAllowRenameFiles(true); $uploader->setFilesDispersion(true); + $uploader->addValidateCallback( + Mage_Core_Model_File_Validator_Image::NAME, + Mage::getModel('core/file_validator_image'), + 'validate' + ); $result = $uploader->save( Mage::getSingleton('catalog/product_media_config')->getBaseTmpMediaPath() ); diff --git a/app/code/core/Mage/Checkout/controllers/MultishippingController.php b/app/code/core/Mage/Checkout/controllers/MultishippingController.php index 9e8293fe6a8..71d3a5498d0 100644 --- a/app/code/core/Mage/Checkout/controllers/MultishippingController.php +++ b/app/code/core/Mage/Checkout/controllers/MultishippingController.php @@ -233,6 +233,12 @@ public function addressesPostAction() $this->_redirect('*/multishipping_address/newShipping'); return; } + + if ($this->isFormkeyValidationOnCheckoutEnabled() && !$this->_validateFormKey()) { + $this->_redirect('*/*/addresses'); + return; + } + try { if ($this->getRequest()->getParam('continue', false)) { $this->_getCheckout()->setCollectRatesFlag(true); @@ -353,6 +359,11 @@ public function backToShippingAction() */ public function shippingPostAction() { + if ($this->isFormkeyValidationOnCheckoutEnabled() && !$this->_validateFormKey()) { + $this->_redirect('*/*/shipping'); + return; + } + $shippingMethods = $this->getRequest()->getPost('shipping_method'); try { Mage::dispatchEvent( @@ -439,6 +450,11 @@ public function overviewAction() return $this; } + if ($this->isFormkeyValidationOnCheckoutEnabled() && !$this->_validateFormKey()) { + $this->_redirect('*/*/billing'); + return; + } + $this->_getState()->setActiveStep(Mage_Checkout_Model_Type_Multishipping_State::STEP_OVERVIEW); try { diff --git a/app/code/core/Mage/Checkout/controllers/OnepageController.php b/app/code/core/Mage/Checkout/controllers/OnepageController.php index 47fb32308d4..9b9f9ff669a 100644 --- a/app/code/core/Mage/Checkout/controllers/OnepageController.php +++ b/app/code/core/Mage/Checkout/controllers/OnepageController.php @@ -350,6 +350,11 @@ public function saveMethodAction() if ($this->_expireAjax()) { return; } + + if ($this->isFormkeyValidationOnCheckoutEnabled() && !$this->_validateFormKey()) { + return; + } + if ($this->getRequest()->isPost()) { $method = $this->getRequest()->getPost('method'); $result = $this->getOnepage()->saveCheckoutMethod($method); @@ -365,6 +370,11 @@ public function saveBillingAction() if ($this->_expireAjax()) { return; } + + if ($this->isFormkeyValidationOnCheckoutEnabled() && !$this->_validateFormKey()) { + return; + } + if ($this->getRequest()->isPost()) { $data = $this->getRequest()->getPost('billing', array()); $customerAddressId = $this->getRequest()->getPost('billing_address_id', false); @@ -407,6 +417,11 @@ public function saveShippingAction() if ($this->_expireAjax()) { return; } + + if ($this->isFormkeyValidationOnCheckoutEnabled() && !$this->_validateFormKey()) { + return; + } + if ($this->getRequest()->isPost()) { $data = $this->getRequest()->getPost('shipping', array()); $customerAddressId = $this->getRequest()->getPost('shipping_address_id', false); @@ -431,6 +446,11 @@ public function saveShippingMethodAction() if ($this->_expireAjax()) { return; } + + if ($this->isFormkeyValidationOnCheckoutEnabled() && !$this->_validateFormKey()) { + return; + } + if ($this->getRequest()->isPost()) { $data = $this->getRequest()->getPost('shipping_method', ''); $result = $this->getOnepage()->saveShippingMethod($data); @@ -465,6 +485,11 @@ public function savePaymentAction() if ($this->_expireAjax()) { return; } + + if ($this->isFormkeyValidationOnCheckoutEnabled() && !$this->_validateFormKey()) { + return; + } + try { if (!$this->getRequest()->isPost()) { $this->_ajaxRedirectResponse(); diff --git a/app/code/core/Mage/Checkout/etc/system.xml b/app/code/core/Mage/Checkout/etc/system.xml index e6af3a9dbfc..1e4bd941437 100644 --- a/app/code/core/Mage/Checkout/etc/system.xml +++ b/app/code/core/Mage/Checkout/etc/system.xml @@ -232,5 +232,23 @@ + + + + + + + select + adminhtml/system_config_source_yesno + 4 + Important! Enabling this option means + that your custom templates used in checkout process contain form_key output. + Otherwise checkout may not work.]]> + 1 + + + + + diff --git a/app/code/core/Mage/Cms/Model/Wysiwyg/Images/Storage.php b/app/code/core/Mage/Cms/Model/Wysiwyg/Images/Storage.php index 810d3a5a00b..394dfa2ed9c 100644 --- a/app/code/core/Mage/Cms/Model/Wysiwyg/Images/Storage.php +++ b/app/code/core/Mage/Cms/Model/Wysiwyg/Images/Storage.php @@ -282,6 +282,11 @@ public function uploadFile($targetPath, $type = null) } $uploader->setAllowRenameFiles(true); $uploader->setFilesDispersion(false); + $uploader->addValidateCallback( + Mage_Core_Model_File_Validator_Image::NAME, + Mage::getModel('core/file_validator_image'), + 'validate' + ); $result = $uploader->save($targetPath); if (!$result) { diff --git a/app/code/core/Mage/Core/Controller/Front/Action.php b/app/code/core/Mage/Core/Controller/Front/Action.php index 5494c1a5406..045acb648ee 100755 --- a/app/code/core/Mage/Core/Controller/Front/Action.php +++ b/app/code/core/Mage/Core/Controller/Front/Action.php @@ -38,6 +38,11 @@ class Mage_Core_Controller_Front_Action extends Mage_Core_Controller_Varien_Acti */ const SESSION_NAMESPACE = 'frontend'; + /** + * Add secret key to url config path + */ + const XML_CSRF_USE_FLAG_CONFIG_PATH = 'system/csrf/use_form_key'; + /** * Currently used area * @@ -159,4 +164,38 @@ protected function _prepareDownloadResponse($fileName, $content, $contentType = } return $this; } + + /** + * Validate Form Key + * + * @return bool + */ + protected function _validateFormKey() + { + $validated = true; + if ($this->_isFormKeyEnabled()) { + $validated = parent::_validateFormKey(); + } + return $validated; + } + + /** + * Check if form key validation is enabled. + * + * @return bool + */ + protected function _isFormKeyEnabled() + { + return Mage::getStoreConfigFlag(self::XML_CSRF_USE_FLAG_CONFIG_PATH); + } + + /** + * Check if form_key validation enabled on checkout process + * + * @return bool + */ + protected function isFormkeyValidationOnCheckoutEnabled() + { + return Mage::getStoreConfigFlag('admin/security/validate_formkey_checkout'); + } } diff --git a/app/code/core/Mage/Core/Controller/Request/Http.php b/app/code/core/Mage/Core/Controller/Request/Http.php index 1735c55dd4d..83f6802abc3 100644 --- a/app/code/core/Mage/Core/Controller/Request/Http.php +++ b/app/code/core/Mage/Core/Controller/Request/Http.php @@ -148,7 +148,10 @@ public function setPathInfo($pathInfo = null) $baseUrl = $this->getBaseUrl(); $pathInfo = substr($requestUri, strlen($baseUrl)); - if ((null !== $baseUrl) && (false === $pathInfo)) { + if ($baseUrl && $pathInfo && (0 !== stripos($pathInfo, '/'))) { + $pathInfo = ''; + $this->setActionName('noRoute'); + } elseif ((null !== $baseUrl) && (false === $pathInfo)) { $pathInfo = ''; } elseif (null === $baseUrl) { $pathInfo = $requestUri; diff --git a/app/code/core/Mage/Core/Model/File/Validator/Image.php b/app/code/core/Mage/Core/Model/File/Validator/Image.php index 7f7b9d045d9..cbbcbb1c80c 100644 --- a/app/code/core/Mage/Core/Model/File/Validator/Image.php +++ b/app/code/core/Mage/Core/Model/File/Validator/Image.php @@ -87,10 +87,33 @@ public function setAllowedImageTypes(array $imageFileExtensions = array()) */ public function validate($filePath) { - $fileInfo = getimagesize($filePath); - if (is_array($fileInfo) and isset($fileInfo[2])) { - if ($this->isImageType($fileInfo[2])) { - return null; + list($imageWidth, $imageHeight, $fileType) = getimagesize($filePath); + if ($fileType) { + if ($this->isImageType($fileType)) { + //replace tmp image with re-sampled copy to exclude images with malicious data + $image = imagecreatefromstring(file_get_contents($filePath)); + if ($image !== false) { + $img = imagecreatetruecolor($imageWidth, $imageHeight); + imagecopyresampled($img, $image, 0, 0, 0, 0, $imageWidth, $imageHeight, $imageWidth, $imageHeight); + switch ($fileType) { + case IMAGETYPE_GIF: + imagegif($img, $filePath); + break; + case IMAGETYPE_JPEG: + imagejpeg($img, $filePath, 100); + break; + case IMAGETYPE_PNG: + imagepng($img, $filePath); + break; + default: + return; + } + imagedestroy($img); + imagedestroy($image); + return null; + } else { + throw Mage::exception('Mage_Core', Mage::helper('core')->__('Invalid image.')); + } } } throw Mage::exception('Mage_Core', Mage::helper('core')->__('Invalid MIME type.')); @@ -105,5 +128,4 @@ protected function isImageType($nImageType) { return in_array($nImageType, $this->_allowedImageTypes); } - } diff --git a/app/code/core/Mage/Core/etc/config.xml b/app/code/core/Mage/Core/etc/config.xml index 8eca50de807..39ce72eebb4 100644 --- a/app/code/core/Mage/Core/etc/config.xml +++ b/app/code/core/Mage/Core/etc/config.xml @@ -274,6 +274,9 @@ + + 1 + 0 localhost diff --git a/app/code/core/Mage/Core/etc/system.xml b/app/code/core/Mage/Core/etc/system.xml index 94fdab21c28..b2f22e2b123 100644 --- a/app/code/core/Mage/Core/etc/system.xml +++ b/app/code/core/Mage/Core/etc/system.xml @@ -529,26 +529,6 @@ - text @@ -819,6 +799,25 @@ 1 1 + + + text + 0 + 1 + 1 + 1 + + + + select + adminhtml/system_config_source_yesno + 10 + 1 + 1 + 1 + + + text @@ -1336,6 +1335,7 @@ text + adminhtml/system_config_backend_web_secure_offloaderheader 75 1 0 diff --git a/app/code/core/Mage/Customer/Model/Session.php b/app/code/core/Mage/Customer/Model/Session.php index 266b06e537b..9918d2157bc 100644 --- a/app/code/core/Mage/Customer/Model/Session.php +++ b/app/code/core/Mage/Customer/Model/Session.php @@ -222,6 +222,8 @@ public function login($username, $password) public function setCustomerAsLoggedIn($customer) { $this->setCustomer($customer); + $this->renewSession(); + Mage::getSingleton('core/session')->renewFormKey(); Mage::dispatchEvent('customer_login', array('customer'=>$customer)); return $this; } @@ -307,6 +309,7 @@ protected function _logout() $this->setId(null); $this->setCustomerGroupId(Mage_Customer_Model_Group::NOT_LOGGED_IN_ID); $this->getCookie()->delete($this->getSessionName()); + Mage::getSingleton('core/session')->renewFormKey(); return $this; } diff --git a/app/code/core/Mage/Dataflow/Model/Convert/Adapter/Zend/Cache.php b/app/code/core/Mage/Dataflow/Model/Convert/Adapter/Zend/Cache.php index 66e03d2486a..88ec799e9c0 100644 --- a/app/code/core/Mage/Dataflow/Model/Convert/Adapter/Zend/Cache.php +++ b/app/code/core/Mage/Dataflow/Model/Convert/Adapter/Zend/Cache.php @@ -40,6 +40,9 @@ public function getResource() if (!$this->_resource) { $this->_resource = Zend_Cache::factory($this->getVar('frontend', 'Core'), $this->getVar('backend', 'File')); } + if ($this->_resource->getBackend() instanceof Zend_Cache_Backend_Static) { + throw new Exception(Mage::helper('dataflow')->__('Backend name "Static" not supported.')); + } return $this->_resource; } diff --git a/app/code/core/Mage/Dataflow/Model/Convert/Container/Abstract.php b/app/code/core/Mage/Dataflow/Model/Convert/Container/Abstract.php index 52f86c09953..d32cd5ab3c1 100644 --- a/app/code/core/Mage/Dataflow/Model/Convert/Container/Abstract.php +++ b/app/code/core/Mage/Dataflow/Model/Convert/Container/Abstract.php @@ -47,6 +47,18 @@ abstract class Mage_Dataflow_Model_Convert_Container_Abstract protected $_position; + /** + * Detect serialization of data + * + * @param mixed $data + * @return bool + */ + protected function isSerialized($data) + { + $pattern = '/^a:\d+:\{(i:\d+;|s:\d+:\".+\";|N;|O:\d+:\"\w+\":\d+:\{\w:\d+:)+|^O:\d+:\"\w+\":\d+:\{s:\d+:\"/'; + return (is_string($data) && preg_match($pattern, $data)); + } + public function getVar($key, $default=null) { if (!isset($this->_vars[$key]) || (!is_array($this->_vars[$key]) && strlen($this->_vars[$key]) == 0)) { @@ -102,13 +114,45 @@ public function getData() public function setData($data) { - if ($this->getProfile()) { - $this->getProfile()->getContainer()->setData($data); + if ($this->validateDataSerialized($data)) { + if ($this->getProfile()) { + $this->getProfile()->getContainer()->setData($data); + } + + $this->_data = $data; } - $this->_data = $data; + return $this; } + /** + * Validate serialized data + * + * @param mixed $data + * @return bool + */ + public function validateDataSerialized($data = null) + { + if (is_null($data)) { + $data = $this->getData(); + } + + $result = true; + if ($this->isSerialized($data)) { + try { + $dataArray = Mage::helper('core/unserializeArray')->unserialize($data); + } catch (Exception $e) { + $result = false; + $this->addException( + "Invalid data, expecting serialized array.", + Mage_Dataflow_Model_Convert_Exception::FATAL + ); + } + } + + return $result; + } + public function validateDataString($data=null) { if (is_null($data)) { @@ -140,7 +184,10 @@ public function validateDataGrid($data=null) if (count($data)==0) { return true; } - $this->addException("Invalid data type, expecting 2D grid array.", Mage_Dataflow_Model_Convert_Exception::FATAL); + $this->addException( + "Invalid data type, expecting 2D grid array.", + Mage_Dataflow_Model_Convert_Exception::FATAL + ); } return true; } diff --git a/app/code/core/Mage/Dataflow/Model/Convert/Parser/Csv.php b/app/code/core/Mage/Dataflow/Model/Convert/Parser/Csv.php index 312df4ee514..66c45eedfba 100644 --- a/app/code/core/Mage/Dataflow/Model/Convert/Parser/Csv.php +++ b/app/code/core/Mage/Dataflow/Model/Convert/Parser/Csv.php @@ -62,13 +62,15 @@ public function parse() $adapter = Mage::getModel($adapterName); } catch (Exception $e) { - $message = Mage::helper('dataflow')->__('Declared adapter %s was not found.', $adapterName); + $message = Mage::helper('dataflow') + ->__('Declared adapter %s was not found.', $adapterName); $this->addException($message, Mage_Dataflow_Model_Convert_Exception::FATAL); return $this; } if (!method_exists($adapter, $adapterMethod)) { - $message = Mage::helper('dataflow')->__('Method "%s" not defined in adapter %s.', $adapterMethod, $adapterName); + $message = Mage::helper('dataflow') + ->__('Method "%s" not defined in adapter %s.', $adapterMethod, $adapterName); $this->addException($message, Mage_Dataflow_Model_Convert_Exception::FATAL); return $this; } @@ -77,8 +79,8 @@ public function parse() $batchIoAdapter = $this->getBatchModel()->getIoAdapter(); if (Mage::app()->getRequest()->getParam('files')) { - $file = Mage::app()->getConfig()->getTempVarDir().'/import/' - . urldecode(Mage::app()->getRequest()->getParam('files')); + $file = Mage::app()->getConfig()->getTempVarDir() . '/import/' + . str_replace('../', '', urldecode(Mage::app()->getRequest()->getParam('files'))); $this->_copy($file); } diff --git a/app/code/core/Mage/Dataflow/Model/Convert/Parser/Xml/Excel.php b/app/code/core/Mage/Dataflow/Model/Convert/Parser/Xml/Excel.php index d25bbf19c6f..57e26c0eb40 100644 --- a/app/code/core/Mage/Dataflow/Model/Convert/Parser/Xml/Excel.php +++ b/app/code/core/Mage/Dataflow/Model/Convert/Parser/Xml/Excel.php @@ -69,7 +69,8 @@ public function parse() } if (!method_exists($adapter, $adapterMethod)) { - $message = Mage::helper('dataflow')->__('Method "%s" was not defined in adapter %s.', $adapterMethod, $adapterName); + $message = Mage::helper('dataflow') + ->__('Method "%s" was not defined in adapter %s.', $adapterMethod, $adapterName); $this->addException($message, Mage_Dataflow_Model_Convert_Exception::FATAL); return $this; } @@ -78,8 +79,8 @@ public function parse() $batchIoAdapter = $this->getBatchModel()->getIoAdapter(); if (Mage::app()->getRequest()->getParam('files')) { - $file = Mage::app()->getConfig()->getTempVarDir().'/import/' - . urldecode(Mage::app()->getRequest()->getParam('files')); + $file = Mage::app()->getConfig()->getTempVarDir() . '/import/' + . str_replace('../', '', urldecode(Mage::app()->getRequest()->getParam('files'))); $this->_copy($file); } diff --git a/app/code/core/Mage/ImportExport/Model/Import/Uploader.php b/app/code/core/Mage/ImportExport/Model/Import/Uploader.php index b4208845b5a..898cbc8877b 100644 --- a/app/code/core/Mage/ImportExport/Model/Import/Uploader.php +++ b/app/code/core/Mage/ImportExport/Model/Import/Uploader.php @@ -61,6 +61,11 @@ public function init() $this->setAllowedExtensions(array_keys($this->_allowedMimeTypes)); $this->addValidateCallback('catalog_product_image', Mage::helper('catalog/image'), 'validateUploadFile'); + $this->addValidateCallback( + Mage_Core_Model_File_Validator_Image::NAME, + Mage::getModel('core/file_validator_image'), + 'validate' + ); $this->_uploadType = self::SINGLE_STYLE; } diff --git a/app/code/core/Mage/Sales/Model/Quote/Item.php b/app/code/core/Mage/Sales/Model/Quote/Item.php index bea33090820..03dee1cce6a 100644 --- a/app/code/core/Mage/Sales/Model/Quote/Item.php +++ b/app/code/core/Mage/Sales/Model/Quote/Item.php @@ -498,8 +498,9 @@ public function compare($item) /** @var Unserialize_Parser $parser */ $parser = Mage::helper('core/unserializeArray'); - $_itemOptionValue = $parser->unserialize($itemOptionValue); - $_optionValue = $parser->unserialize($optionValue); + $_itemOptionValue = + is_numeric($itemOptionValue) ? $itemOptionValue : $parser->unserialize($itemOptionValue); + $_optionValue = is_numeric($optionValue) ? $optionValue : $parser->unserialize($optionValue); if (is_array($_itemOptionValue) && is_array($_optionValue)) { $itemOptionValue = $_itemOptionValue; diff --git a/app/code/core/Mage/Tax/Model/Calculation.php b/app/code/core/Mage/Tax/Model/Calculation.php index 38355c4c744..9a4f8b8e1fb 100644 --- a/app/code/core/Mage/Tax/Model/Calculation.php +++ b/app/code/core/Mage/Tax/Model/Calculation.php @@ -553,6 +553,17 @@ public function getAppliedRates($request) return $this->_rateCalculationProcess[$cacheKey]; } + /** + * Get rate ids applicable for some address + * + * @param Varien_Object $request + * @return array + */ + public function getApplicableRateIds($request) + { + return $this->_getResource()->getApplicableRateIds($request); + } + /** * Get the calculation process * diff --git a/app/code/core/Mage/Tax/Model/Resource/Calculation.php b/app/code/core/Mage/Tax/Model/Resource/Calculation.php index bb447725501..3e0e30f8678 100755 --- a/app/code/core/Mage/Tax/Model/Resource/Calculation.php +++ b/app/code/core/Mage/Tax/Model/Resource/Calculation.php @@ -361,6 +361,35 @@ protected function _getRates($request) return $this->_ratesCache[$cacheKey]; } + /** + * Get rate ids applicable for some address + * + * @param Varien_Object $request + * @return array + */ + function getApplicableRateIds($request) + { + $countryId = $request->getCountryId(); + $regionId = $request->getRegionId(); + $postcode = $request->getPostcode(); + + $select = $this->_getReadAdapter()->select() + ->from(array('rate' => $this->getTable('tax/tax_calculation_rate')), array('tax_calculation_rate_id')) + ->where('rate.tax_country_id = ?', $countryId) + ->where("rate.tax_region_id IN(?)", array(0, (int)$regionId)); + + $expr = $this->_getWriteAdapter()->getCheckSql( + 'zip_is_range is NULL', + $this->_getWriteAdapter()->quoteInto( + "rate.tax_postcode IS NULL OR rate.tax_postcode IN('*', '', ?)", + $this->_createSearchPostCodeTemplates($postcode) + ), + $this->_getWriteAdapter()->quoteInto('? BETWEEN rate.zip_from AND rate.zip_to', $postcode) + ); + $select->where($expr); + return $this->_getReadAdapter()->fetchCol($select); + } + /** * Calculate rate * diff --git a/app/code/core/Mage/Widget/Model/Widget/Instance.php b/app/code/core/Mage/Widget/Model/Widget/Instance.php index f070c6d1035..faddd1647ff 100644 --- a/app/code/core/Mage/Widget/Model/Widget/Instance.php +++ b/app/code/core/Mage/Widget/Model/Widget/Instance.php @@ -347,7 +347,11 @@ public function getStoreIds() public function getWidgetParameters() { if (is_string($this->getData('widget_parameters'))) { - return unserialize($this->getData('widget_parameters')); + try { + return Mage::helper('core/unserializeArray')->unserialize($this->getData('widget_parameters')); + } catch (Exception $e) { + Mage::logException($e); + } } return (is_array($this->getData('widget_parameters'))) ? $this->getData('widget_parameters') : array(); } diff --git a/app/code/core/Mage/XmlConnect/Helper/Image.php b/app/code/core/Mage/XmlConnect/Helper/Image.php index c3d1d920094..573be065bd9 100644 --- a/app/code/core/Mage/XmlConnect/Helper/Image.php +++ b/app/code/core/Mage/XmlConnect/Helper/Image.php @@ -100,6 +100,11 @@ public function handleUpload($field) $uploader = Mage::getModel('core/file_uploader', $field); $uploader->setAllowedExtensions(array('jpg', 'jpeg', 'gif', 'png')); $uploader->setAllowRenameFiles(true); + $uploader->addValidateCallback( + Mage_Core_Model_File_Validator_Image::NAME, + Mage::getModel('core/file_validator_image'), + 'validate' + ); $uploader->save($uploadDir); $uploadedFilename = $uploader->getUploadedFileName(); $uploadedFilename = $this->_getResizedFilename($field, $uploadedFilename, true); diff --git a/app/code/core/Mage/XmlConnect/controllers/Adminhtml/MobileController.php b/app/code/core/Mage/XmlConnect/controllers/Adminhtml/MobileController.php index 5532c878d54..0f293b363ff 100644 --- a/app/code/core/Mage/XmlConnect/controllers/Adminhtml/MobileController.php +++ b/app/code/core/Mage/XmlConnect/controllers/Adminhtml/MobileController.php @@ -567,7 +567,7 @@ public function deleteThemeAction() $result = $themesHelper->deleteTheme($themeId); if ($result) { $response = array( - 'message' => $this->__('Theme has been delete.'), + 'message' => $this->__('Theme has been deleted.'), 'themes' => $themesHelper->getAllThemesArray(true), 'themeSelector' => $themesHelper->getThemesSelector(), 'selectedTheme' => $themesHelper->getDefaultThemeName() @@ -1393,6 +1393,11 @@ public function uploadImagesAction() /** @var $uploader Mage_Core_Model_File_Uploader */ $uploader = Mage::getModel('core/file_uploader', $imageModel->getImageType()); $uploader->setAllowRenameFiles(true)->setAllowedExtensions(array('jpg', 'jpeg', 'gif', 'png')); + $uploader->addValidateCallback( + Mage_Core_Model_File_Validator_Image::NAME, + Mage::getModel('core/file_validator_image'), + 'validate' + ); $result = $uploader->save(Mage_XmlConnect_Model_Images::getBasePath(), $newFileName); $result['thumbnail'] = Mage::getModel('xmlconnect/images')->getCustomSizeImageUrl( $result['file'], diff --git a/app/design/adminhtml/default/default/layout/main.xml b/app/design/adminhtml/default/default/layout/main.xml index 566b1c5b0b6..e2409c14481 100644 --- a/app/design/adminhtml/default/default/layout/main.xml +++ b/app/design/adminhtml/default/default/layout/main.xml @@ -119,7 +119,8 @@ Default layout, loads most of the pages - + + diff --git a/app/design/adminhtml/default/default/template/notification/formkey.phtml b/app/design/adminhtml/default/default/template/notification/formkey.phtml new file mode 100644 index 00000000000..ec99a74f76e --- /dev/null +++ b/app/design/adminhtml/default/default/template/notification/formkey.phtml @@ -0,0 +1,38 @@ + +canShow()): ?> +
+ Important: + Formkey validation on checkout disabled. This may expose security risks. + We strongly recommend to Enable Form Key Validation On Checkout in + Admin / Security Section, + for protect your own checkout process. +
+ diff --git a/app/design/adminhtml/default/default/template/notification/symlink.phtml b/app/design/adminhtml/default/default/template/notification/symlink.phtml new file mode 100644 index 00000000000..2a609011390 --- /dev/null +++ b/app/design/adminhtml/default/default/template/notification/symlink.phtml @@ -0,0 +1,34 @@ + +isSymlinkEnabled()): ?> +
+ helper('adminhtml')->__('Symlinks are enabled. This may expose security risks. We strongly recommend to disable them.')?> +
+ diff --git a/app/design/adminhtml/default/default/template/page/head.phtml b/app/design/adminhtml/default/default/template/page/head.phtml index ef6371f7589..3f944dc484a 100644 --- a/app/design/adminhtml/default/default/template/page/head.phtml +++ b/app/design/adminhtml/default/default/template/page/head.phtml @@ -7,7 +7,7 @@ var BLANK_URL = 'getJsUrl() ?>blank.html'; var BLANK_IMG = 'getJsUrl() ?>spacer.gif'; var BASE_URL = 'getUrl('*') ?>'; - var SKIN_URL = 'getSkinUrl() ?>'; + var SKIN_URL = 'jsQuoteEscape($this->getSkinUrl()) ?>'; var FORM_KEY = 'getFormKey() ?>'; diff --git a/app/design/frontend/base/default/template/checkout/cart/shipping.phtml b/app/design/frontend/base/default/template/checkout/cart/shipping.phtml index 926626229e9..43f29a0e66c 100644 --- a/app/design/frontend/base/default/template/checkout/cart/shipping.phtml +++ b/app/design/frontend/base/default/template/checkout/cart/shipping.phtml @@ -109,6 +109,7 @@
+ getBlockHtml('formkey') ?>