Skip to content

Potential authenticated Remote Code Execution via malicious attached Behavior

High
angrybrad published GHSA-2fph-6v5w-89hh Mar 24, 2026

Package

composer craftcms/cms (Composer)

Affected versions

>= 5.6.0, <= 5.9.12

Patched versions

5.9.13

Description

Summary

A Remote Code Execution (RCE) vulnerability exists in Craft CMS 5.x and 4.x that bypasses the security fixes for GHSA-7jx7-3846-m7w7 and GHSA-255j-qw47-wjh5. This vulnerability can be exploited by any authenticated user with control panel access.

The existing patches add cleanseConfig() to assembleLayoutFromPost() and various FieldsController actions to strip Yii2 behavior/event injection keys (as and on prefixed keys). However, the fieldLayouts parameter in ElementIndexesController::actionFilterHud() is passed directly to FieldLayout::createFromConfig() without any sanitization, enabling the same behavior injection attack chain.

Impact

  • Attack Type: Remote Code Execution (RCE)
  • Authentication Required: Authenticated user with control panel access (accessCp permission)

Vulnerability Details

Root Cause

In ElementIndexesController::actionFilterHud() (line 493-494), the fieldLayouts body parameter is passed to FieldLayout::createFromConfig() without cleanseConfig():

// ElementIndexesController.php:485-494
if ($conditionConfig) {
    $conditionConfig = Component::cleanseConfig($conditionConfig); // conditionConfig IS cleansed
    $condition = $conditionsService->createCondition($conditionConfig);
} else {
    $condition = $this->elementType()::createCondition();
}

if (!empty($fieldLayouts)) {
    // fieldLayouts is NOT cleansed!
    $condition->setFieldLayouts(array_map(
        fn(array $config) => FieldLayout::createFromConfig($config),
        $fieldLayouts
    ));
}

Note the inconsistency: conditionConfig is sanitized with cleanseConfig(), but fieldLayouts is not.

Attack Chain

  1. Send a fieldLayouts array containing config with "as <name>" prefixed keys
  2. FieldLayout::createFromConfig($config) -> new self($config) -> Model::__construct($config)
  3. App::configure($this, $config) processes each key
  4. "as rce" key -> Component::__set("as rce", $value) -> Yii::createObject($value) -> instantiates AttributeTypecastBehavior and attaches it to the FieldLayout
  5. "on *" key -> registers a wildcard event handler
  6. parent::__construct() -> init() -> setTabs([]) -> getAvailableNativeFields() -> trigger(EVENT_DEFINE_NATIVE_FIELDS)
  7. The wildcard handler fires -> AttributeTypecastBehavior::beforeSave() -> typecastAttributes()
  8. $this->owner->typecastBeforeSave -> resolved via Component::__get() -> returns the command string from the behavior's own property
  9. call_user_func([ConsoleProcessus::class, 'execute'], $command) -> shell_exec($command)

Prerequisites

  • A user account with control panel access

References

Severity

High

CVE ID

CVE-2026-33157

Weaknesses

No CWEs

Credits