fix/security-audit

This commit is contained in:
2026-10-26 17:44:54 +03:00
committed by Git Moneta
parent 1f29a07f63
commit d850c2ca31
8 changed files with 389 additions and 113 deletions
@@ -8,8 +8,7 @@
*/
class ControllerExtensionPaymentPayanyway extends Controller {
const CMS_NAME = 'OpenCart';
const MODULE_NAME = 'payanyway';
const MODULE_VERSION = '1.0.5';
const MODULE_VERSION = '1.0.6';
const MODULE_DEFAULT_SORT_ORDER = 0;
/** Маркер вставки OCMOD из install.xml в роутере витрины (приём Check/Pay URL методом POST). */
@@ -30,7 +29,6 @@ class ControllerExtensionPaymentPayanyway extends Controller {
'vat122' => '1114'
);
/** Признак способа расчёта (kassaspecification.pdf, pm). */
private $paymentMethods = array(
'full_prepayment',
'prepayment',
@@ -41,7 +39,6 @@ class ControllerExtensionPaymentPayanyway extends Controller {
'credit_payment'
);
/** Признак предмета расчёта (kassaspecification.pdf, po). */
private $paymentObjects = array(
'commodity',
'excise',
@@ -108,7 +105,9 @@ class ControllerExtensionPaymentPayanyway extends Controller {
$data['payment_payanyway_status'] = $this->retrieveValue('payment_payanyway_status');
$data['payment_payanyway_account'] = $this->retrieveValue('payment_payanyway_account');
$data['payment_payanyway_integrity_code'] = $this->getIntegrityCode('payment_payanyway_integrity_code');
$data['integrity_code_placeholder'] = $this->hasIntegrityCode()
? $this->language->get('text_integrity_code_saved')
: $this->language->get('entry_integrity_code_description');
$data['payment_payanyway_server'] = $this->retrieveValue('payment_payanyway_server');
$data['payment_payanyway_test_mode'] = (string)$this->retrieveValue('payment_payanyway_test_mode');
$data['payment_payanyway_fiscalization'] = $this->isFiscalizationEnabled() ? '1' : '0';
@@ -182,7 +181,8 @@ class ControllerExtensionPaymentPayanyway extends Controller {
'payment_payanyway_integrity_code' => '',
'payment_payanyway_server' => 'prod',
'payment_payanyway_test_mode' => 0,
'payment_payanyway_fiscalization' => 1,
'payment_payanyway_fiscalization' => 0,
'payment_payanyway_vat_rate' => $this->availableVatRates['vat_none'],
'payment_payanyway_receipt_email' => '',
'payment_payanyway_payment_method' => self::DEFAULT_PAYMENT_METHOD,
'payment_payanyway_payment_object' => self::DEFAULT_PAYMENT_OBJECT,
@@ -246,9 +246,10 @@ class ControllerExtensionPaymentPayanyway extends Controller {
$this->error['account'] = $this->language->get('error_account');
}
// OpenCart экранирует весь POST (htmlspecialchars в system/library/request.php): код с & " < >
// сохранился бы экранированным, и подписи не сошлись бы с MONETA.RU.
$integrityCode = $this->decodePostedString($request, 'payment_payanyway_integrity_code');
if (('' === $integrityCode) && $this->hasIntegrityCode()) {
$integrityCode = (string)$this->config->get('payment_payanyway_integrity_code');
}
if ('' === $integrityCode) {
$this->error['integrity_code'] = $this->language->get('error_integrity_code');
}
@@ -278,7 +279,9 @@ class ControllerExtensionPaymentPayanyway extends Controller {
$canceled = isset($request->post['payment_payanyway_canceled_order_status_ids'])
? (array)$request->post['payment_payanyway_canceled_order_status_ids']
: array();
$request->post['payment_payanyway_canceled_order_status_ids'] = array_values(array_unique(array_map('intval', $canceled)));
$request->post['payment_payanyway_canceled_order_status_ids'] = array_values(array_unique(array_filter(array_map('intval', $canceled), function ($statusId) {
return $statusId > 0;
})));
if (empty($request->post['payment_payanyway_pending_order_status_id'])) {
$this->error['pending_order_status'] = $this->language->get('error_order_status');
@@ -290,6 +293,19 @@ class ControllerExtensionPaymentPayanyway extends Controller {
$this->error['error_order_status'] = $this->language->get('error_order_status');
}
// Статус ожидания или ошибки среди отменённых: Check и Pay URL ответили бы на настоящую оплату
// 500, и MONETA.RU прекратила бы уведомления — деньги списаны, заказ не оплачен.
$moduleStatuses = array();
foreach (array('pending', 'success', 'error') as $status) {
$key = 'payment_payanyway_' . $status . '_order_status_id';
if (!empty($request->post[$key])) {
$moduleStatuses[] = (int)$request->post[$key];
}
}
if (array_intersect($request->post['payment_payanyway_canceled_order_status_ids'], $moduleStatuses)) {
$this->error['canceled_order_status'] = $this->language->get('error_canceled_order_status');
}
$sortOrder = isset($request->post['payment_payanyway_sort_order'])
? (int)$request->post['payment_payanyway_sort_order']
: self::MODULE_DEFAULT_SORT_ORDER;
@@ -311,6 +327,7 @@ class ControllerExtensionPaymentPayanyway extends Controller {
$data['error_pending_order_status'] = isset($this->error['pending_order_status']) ? $this->error['pending_order_status'] : '';
$data['error_success_order_status'] = isset($this->error['success_order_status']) ? $this->error['success_order_status'] : '';
$data['error_error_order_status'] = isset($this->error['error_order_status']) ? $this->error['error_order_status'] : '';
$data['error_canceled_order_status'] = isset($this->error['canceled_order_status']) ? $this->error['canceled_order_status'] : '';
}
/** @return array<int, array{text: string, href: string}> */
@@ -331,12 +348,9 @@ class ControllerExtensionPaymentPayanyway extends Controller {
);
}
/**
* @param string $key
* @return string
*/
private function getIntegrityCode($key) {
return htmlspecialchars((string)$this->retrieveRawValue($key), ENT_QUOTES, 'UTF-8');
/** @return bool код проверки целостности уже сохранён */
private function hasIntegrityCode() {
return '' !== (string)$this->config->get('payment_payanyway_integrity_code');
}
/**