Skip to content

Commit

Permalink
Fixed an RCE vulnerability
Browse files Browse the repository at this point in the history
  • Loading branch information
brandonkelly committed Jun 27, 2023
1 parent c0a37e1 commit 7359d18
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 1 deletion.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Expand Up @@ -6,8 +6,10 @@
- The `up`, `migrate/up`, and `migrate/all` commands now revert any project config changes created by migrations on failure.
- The `up`, `migrate/up`, and `migrate/all` commands now prompt to restore the backup created at the outset of the command, or recommend restoring a backup, on failure.
- Added `craft\console\controllers\BackupTrait::restore()`.
- Added `craft\helpers\Component::cleanseConfig()`.
- Fixed a bug where Single entries weren’t getting preloaded for template macros, if the template body wasn‘t rendered. ([#13312](https://github.com/craftcms/cms/issues/13312))
- Fixed a bug where asset folders could get dynamically created for elements with temporary slugs. ([#13311](https://github.com/craftcms/cms/issues/13311))
- Fixed an RCE vulnerability.

## 4.4.14 - 2023-06-13

Expand Down
3 changes: 2 additions & 1 deletion src/controllers/ConditionsController.php
Expand Up @@ -11,6 +11,7 @@
use craft\base\conditions\ConditionInterface;
use craft\base\conditions\ConditionRuleInterface;
use craft\helpers\ArrayHelper;
use craft\helpers\Component;
use craft\helpers\Json;
use craft\web\Controller;
use Illuminate\Support\Collection;
Expand Down Expand Up @@ -41,7 +42,7 @@ public function beforeAction($action): bool
$this->requireCpRequest();

$baseConfig = Json::decodeIfJson($this->request->getBodyParam('config'));
$config = $this->request->getBodyParam($baseConfig['name']);
$config = Component::cleanseConfig($this->request->getBodyParam($baseConfig['name']));
$newRuleType = ArrayHelper::remove($config, 'new-rule-type');
$conditionsService = Craft::$app->getConditions();
$this->_condition = $conditionsService->createCondition($config);
Expand Down
21 changes: 21 additions & 0 deletions src/helpers/Component.php
Expand Up @@ -81,6 +81,27 @@ public static function validateComponentClass(string $class, ?string $instanceOf
return true;
}

/**
* Cleanses a component config of any `on X` or `as X` keys.
*
* @param array $config
* @return array
* @since 4.4.15
*/
public static function cleanseConfig(array $config): array
{
foreach ($config as $key => $value) {
if (is_string($key) && (str_starts_with($key, 'on ') || str_starts_with($key, 'as '))) {
unset($config[$key]);
continue;
}
if (is_array($value)) {
$config[$key] = static::cleanseConfig($value);
}
}
return $config;
}

/**
* Instantiates and populates a component, and ensures that it is an instance of a given interface.
*
Expand Down
27 changes: 27 additions & 0 deletions tests/unit/helpers/ComponentHelperTest.php
Expand Up @@ -115,6 +115,16 @@ public function testIconSvg(string $needle, ?string $icon, string $label): void
self::assertStringContainsString($needle, Component::iconSvg($icon, $label));
}

/**
* @dataProvider cleanseConfigDataProvider
* @param array $expected
* @param array $config
*/
public function testCleanseConfig(array $expected, array $config)
{
self::assertSame($expected, Component::cleanseConfig($config));
}

/**
* @return array
*/
Expand Down Expand Up @@ -304,4 +314,21 @@ public function iconSvgDataProvider(): array
'aria-hidden' => ['aria-hidden="true"', '<svg width="100px" height="100px" viewBox="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"></svg>', 'Default'],
];
}

/**
* @return array
*/
public function cleanseConfigDataProvider(): array
{
return [
[
['f' => 'foo', 'b' => 'bar'],
['f' => 'foo', 'b' => 'bar', 'as f' => 'f', 'on b' => 'b'],
],
[
['nested' => ['f' => 'foo', 'b' => 'bar']],
['nested' => ['f' => 'foo', 'b' => 'bar', 'as f' => 'f', 'on b' => 'b']],
],
];
}
}

0 comments on commit 7359d18

Please sign in to comment.