-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #3 from wubinworks/issue-1-php7-support
Support Magento 2.3 and PHP 7
- Loading branch information
Showing
7 changed files
with
363 additions
and
86 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
<?php | ||
/** | ||
* Copyright © Wubinworks. All rights reserved. | ||
* See COPYING.txt for license details. | ||
*/ | ||
declare(strict_types=1); | ||
|
||
namespace Wubinworks\CosmicStingPatch\Model; | ||
|
||
use Laminas\Http\PhpEnvironment\RemoteAddress as LaminasHttpRemoteAddress; | ||
use Zend\Http\PhpEnvironment\RemoteAddress as ZendHttpRemoteAddress; | ||
use Magento\Framework\HTTP\PhpEnvironment\Request; | ||
|
||
/** | ||
* Request information | ||
*/ | ||
class RequestInfo | ||
{ | ||
public const INFO_KEYS = [ | ||
'ip', | ||
'request_line', | ||
'body' | ||
]; | ||
|
||
/** | ||
* @var Request | ||
*/ | ||
protected $request; | ||
|
||
/** | ||
* Constructor | ||
* | ||
* @param Request $request | ||
*/ | ||
public function __construct( | ||
Request $request | ||
) { | ||
$this->request = $request; | ||
} | ||
|
||
/** | ||
* Get request information | ||
* | ||
* @param ?string $key | ||
* @return string|string[] | ||
* | ||
* @throws \InvalidArgumentException | ||
*/ | ||
public function getRequestInfo(?string $key = null) | ||
{ | ||
$info = [ | ||
'ip' => (string)$this->getRemoteAddress(), // `false` converted to empty string | ||
'request_line' => $this->getRequestLine(), | ||
'body' => $this->getRequestBody() | ||
]; | ||
if ($key === null) { | ||
return $info; | ||
} | ||
if (!array_key_exists($key, $info)) { | ||
throw new \InvalidArgumentException(sprintf( | ||
'Unknown key %s was used to retrieve RequestInfo.', | ||
$key | ||
)); | ||
} | ||
return $info[$key]; | ||
} | ||
|
||
/** | ||
* Get correct remote IP address | ||
* | ||
* @return string|bool `false` if failed | ||
*/ | ||
protected function getRemoteAddress() | ||
{ | ||
if (class_exists(LaminasHttpRemoteAddress::class)) { | ||
$httpRemoteAddressClass = LaminasHttpRemoteAddress::class; | ||
} else { | ||
$httpRemoteAddressClass = ZendHttpRemoteAddress::class; | ||
} | ||
|
||
$ip = (new $httpRemoteAddressClass())->getIpAddress(); | ||
if ($ip) { | ||
return filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6); | ||
} | ||
|
||
return false; | ||
} | ||
|
||
/** | ||
* Get request line | ||
* | ||
* @return string | ||
*/ | ||
protected function getRequestLine(): string | ||
{ | ||
return (string)$this->request->renderRequestLine(); | ||
} | ||
|
||
/** | ||
* Get request body with limited length | ||
* | ||
* @param int $maxLength | ||
* @return string | ||
*/ | ||
protected function getRequestBody(int $maxLength = 1000): string | ||
{ | ||
return mb_substr((string)$this->request->getContent(), 0, $maxLength); | ||
} | ||
} |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,164 @@ | ||
<?php | ||
/** | ||
* Copyright © Wubinworks. All rights reserved. | ||
* See COPYING.txt for license details. | ||
*/ | ||
declare(strict_types=1); | ||
|
||
namespace Wubinworks\CosmicStingPatch\Plugin\Framework\Webapi; | ||
|
||
use Magento\Framework\Phrase; | ||
use Magento\Framework\Exception\SerializationException; | ||
use Wubinworks\CosmicStingPatch\Model\RequestInfo; | ||
|
||
/** | ||
* Patch for CVE-2024-34102(aka Cosmic Sting) | ||
* | ||
* @link https://nvd.nist.gov/vuln/detail/CVE-2024-34102 | ||
* @link https://helpx.adobe.com/security/products/magento/apsb24-40.html | ||
* @link https://experienceleague.adobe.com/en/docs/commerce-knowledge-base/kb/troubleshooting/known-issues-patches-attached/security-update-available-for-adobe-commerce-apsb24-40-revised-to-include-isolated-patch-for-cve-2024-34102 | ||
*/ | ||
class ServiceInputProcessor | ||
{ | ||
/** | ||
* Including inherited classes | ||
* | ||
* @var string[] | ||
*/ | ||
protected $forbiddenClasses = [ | ||
\SimpleXMLElement::class, | ||
\DOMElement::class | ||
]; | ||
|
||
/** | ||
* @var RequestInfo | ||
*/ | ||
protected $requestInfo; | ||
|
||
/** | ||
* @var \Psr\Log\LoggerInterface | ||
*/ | ||
protected $logger; | ||
|
||
/** | ||
* @var array | ||
*/ | ||
protected $loggerConfig; | ||
|
||
/** | ||
* Constructor | ||
* | ||
* @param RequestInfo $requestInfo | ||
* @param \Psr\Log\LoggerInterface $logger | ||
* @param array $loggerConfig | ||
*/ | ||
public function __construct( | ||
RequestInfo $requestInfo, | ||
\Psr\Log\LoggerInterface $logger, | ||
array $loggerConfig = [] | ||
) { | ||
$this->requestInfo = $requestInfo; | ||
$this->logger = $logger; | ||
$this->loggerConfig = array_merge($this->_initLoggerConfig(), $loggerConfig); | ||
} | ||
|
||
/** | ||
* Before plugin to detect forbidden type | ||
* | ||
* @param \Magento\Framework\Webapi\ServiceInputProcessor $subject | ||
* @param mixed $data | ||
* @param string $type | ||
* @return null | ||
* | ||
* @throws SerializationException | ||
* @SuppressWarnings(PHPMD.UnusedFormalParameter) | ||
*/ | ||
public function beforeConvertValue( | ||
\Magento\Framework\Webapi\ServiceInputProcessor $subject, | ||
$data, | ||
$type | ||
) { | ||
$type = (string)$type; | ||
if ($this->isForbiddenType($type)) { | ||
$message = $this->prepareLogMessage(); | ||
if ($message) { | ||
$this->logger->info($message); | ||
} | ||
throw new SerializationException( | ||
new Phrase('Invalid data type detected in deserialization process.') | ||
); | ||
} | ||
|
||
return null; | ||
} | ||
|
||
/** | ||
* Check forbidden type | ||
* | ||
* @param string $type | ||
* @return bool | ||
*/ | ||
protected function isForbiddenType(string $type): bool | ||
{ | ||
foreach ($this->forbiddenClasses as $forbiddenClass) { | ||
if (is_subclass_of($type, $forbiddenClass)) { | ||
return true; | ||
} | ||
} | ||
return false; | ||
} | ||
|
||
/** | ||
* Prepare log message | ||
* | ||
* @return string | ||
*/ | ||
protected function prepareLogMessage(): string | ||
{ | ||
if (!$this->isLoggerEnabled()) { | ||
return ''; | ||
} | ||
|
||
$message = 'Detected possible Cosmic Sting attack.' . "\n"; | ||
if ($this->loggerConfig['ip']['enabled']) { | ||
$message .= 'IP: ' . $this->requestInfo->getRequestInfo('ip') . "\n"; | ||
} | ||
if ($this->loggerConfig['request_line']['enabled']) { | ||
$message .= $this->requestInfo->getRequestInfo('request_line') . "\n"; | ||
} | ||
if ($this->loggerConfig['body']['enabled']) { | ||
$message .= $this->requestInfo->getRequestInfo('body') . "\n"; | ||
} | ||
|
||
return $message; | ||
} | ||
|
||
/** | ||
* Initialize logger config | ||
* | ||
* @return array | ||
*/ | ||
protected function _initLoggerConfig(): array | ||
{ | ||
$result = []; | ||
foreach (RequestInfo::INFO_KEYS as $key) { | ||
$result[$key]['enabled'] = false; | ||
} | ||
return $result; | ||
} | ||
|
||
/** | ||
* Check logger enabled | ||
* | ||
* @return bool | ||
*/ | ||
protected function isLoggerEnabled(): bool | ||
{ | ||
foreach ($this->loggerConfig as $item) { | ||
if ($item['enabled']) { | ||
return true; | ||
} | ||
} | ||
return false; | ||
} | ||
} |
Oops, something went wrong.