펜리젠트 헤더

CVE-2026-44011: Craft CMS Behavior Injection and Authenticated RCE

CVE-2026-44011 is an authenticated remote code execution issue in Craft CMS’s handling of object configuration. An account permitted to interact with the application can reach a boundary where request data influences runtime behavior, rather than merely supplying values for a search or condition. The Craft advisory identifies fixes in 4.17.12 and 5.9.18. Owners should use a currently supported, patched release in the appropriate branch.

The revealing detail is the placement of the correction. Craft already had a helper for removing behavior and event-handler configuration. The referenced fix adds that cleansing step to condition-processing paths before the application creates an object. A useful review therefore asks where untrusted configuration becomes a live component. Finding the helper somewhere in the codebase, or confirming that a request requires login, does not answer that question.

Match the Craft branch before planning the update

The affected ranges below come from the vendor’s package advisory. They are historical remediation boundaries for this issue, not a recommendation to install an old fixed version over a newer supported release. A deployment on an unfamiliar branch needs its own vendor support check.

패키지Affected rangeFirst fixed release listed
craftcms/cms 4.x4.0.0 up to, excluding, 4.17.124.17.12
craftcms/cms 5.x5.0.0 up to, excluding, 5.9.185.9.18

An authenticated application user is not supposed to inherit the PHP service account’s authority. Keep that distinction in the exposure assessment: restricting login reduces the set of possible callers, while the configuration boundary determines what an accepted caller can cause the server to do.

The advisory was published in April 2026. Renewed interest in its CVE identifier in October does not make it a newly disclosed October zero-day. The sources reviewed here provide the vendor’s reproduction and correction; they do not establish a new October exploitation campaign. Treat any incident claim as a separate fact that needs its own evidence.

Why a configuration array can carry more authority than it appears to

Yii configuration is a construction interface. The Yii configuration guide documents ordinary property assignment alongside event handlers and attached behaviors. Entries beginning with on configure event handling; entries beginning with as attach behaviors. In trusted application configuration, those features let developers assemble components without writing a custom subclass for every variation.

The security problem begins when a product accepts a user’s structured settings and passes them into that richer construction language. A field that looks like a nested settings object at the HTTP boundary can become instructions about what object to build or what behavior to attach. Valid JSON syntax is irrelevant to whether the caller should control those instructions. Parsing establishes structure, not authority.

Consider the intended task of an editorial condition: select content matching some permitted attributes. The caller may legitimately supply filter values, yet have no reason to choose lifecycle callbacks. Those capabilities belong to different trust levels even when they fit into the same PHP array. The application needs to preserve that distinction as the data moves from request parsing into component creation.

This is also why describing every such issue as PHP object deserialization can mislead a code review. The path under discussion involves framework-driven object configuration. Searching only for 직렬화 해제() would miss the relevant transition. Reviewers need to follow construction helpers and initialization behavior as well as serialization APIs.

The missing check matters before construction

Craft’s Component helper reference describes cleanseConfig() as removing event-handler and behavior keys. Its existence predates this CVE’s fixed releases. That makes the distinction between a defensive API and a defended call site particularly important: an available safeguard protects only paths that invoke it at the right time.

그리고 fix linked by the advisory changes two controllers. In ElementIndexSettingsController, it assigns the posted condition to a local value and cleanses array configuration before passing it to condition creation. In ElementIndexesController, it adds the corresponding array check and cleansing before creating a condition. The important change is the order: constrain the configuration, then construct the component.

That ordering prevents a common repair mistake. If construction can attach behavior or invoke initialization logic, inspecting the resulting object afterward may be too late to prevent a side effect. A type check on the returned component can still be useful, but it answers what object came back. It cannot undo work performed while that object was being built.

The nested structure explains why checking only the outer condition type is insufficient. The advisory’s technical description identifies field-layout data becoming a live object and a lifecycle event occurring during initialization. A benign outer component can contain configuration that grants behavior to an inner one. Validation must cover the structure interpreted by the factory, not merely confirm that the top-level request is an array.

For a plugin review, sketch the construction tree before selecting a validation rule. Mark which nodes come from server-defined component choices and which contain user-supplied values. If a nested node crosses from the second category into the first without a check, moving the final type assertion will not solve the authority problem. This is a review method derived from the disclosed boundary, not a claim that another plugin has the same flaw.

Read the change as a correction to specific entry paths, not proof that every arbitrary configuration feature is safe for untrusted input. A plugin may introduce its own request-to-object conversion. A custom controller may reuse the same factory with different data. The review question remains local and concrete: which part of this configuration may the requester select, and which server-controlled construction decisions must remain fixed?

Craft CMS configuration cleansing before object creation, separating request values from behavior and event-handler instructions.
Conceptual data boundary based on the advisory and linked fix. The check belongs before object construction.

Use the patch to guide a focused extension review

Start at code that accepts conditions, layout settings, or other nested component descriptions from a request. Trace the data until the first factory, constructor, or model-hydration operation. Do not begin by assuming that every nested array is dangerous; identify which consumer interprets the structure as object configuration. A settings object used only as plain values has a different authority from one accepted by a component factory.

For each transition, write down the fields the business operation actually needs. Search text, selected fields, and supported operators can often be represented as a small schema with bounded types. A caller should not gain permission to select arbitrary classes or attach callbacks merely because the same factory supports those features for trusted configuration.

An allowlist also makes failures easier to test. Unknown construction keys should be rejected or removed before object creation, while legitimate nested condition values should survive. A useful regression case checks both sides. Blocking every customized condition may eliminate the attack path by breaking the feature, which is not an acceptable application repair.

The vendor helper is part of the supported correction; an ad hoc blacklist copied into a reverse proxy is not an equivalent replacement. Encodings, nested objects, and alternate entry paths make an HTTP text rule a poor substitute for the application’s configuration boundary. Use a compensating restriction only with a clear account of which path it covers and keep the supported update as the software remedy.

Distinguish the lock file from the installed deployment

Run dependency inspection from the application’s release directory, using the Composer installation and permissions appropriate to that environment. The documented Composer show command supports inspecting the installed package and, separately, the lock-file entry:

composer show craftcms/cms
composer show --locked craftcms/cms

These are documented inspection examples, not commands executed against a Craft deployment for this article. The first inspects installed package information; the second reads the locked dependency record. Compare the results instead of assuming they must agree. An updated repository lock file can coexist with an older deployed vendor directory if the installation step did not reach the serving release.

Deployment layouts add another source of confusion. A release directory checked in a terminal may not be the directory selected by the web server’s active release link. A container image built with the fix may not be the image serving traffic. Record the application artifact and serving instance together. In a multi-instance site, verify the rollout rather than extrapolating from the first corrected node.

A locally maintained fork or backport needs more than a version string. Retain the patch provenance and confirm that the relevant pre-construction checks are present in the deployed code. Conversely, do not apply a public proof of concept to production merely to compensate for missing build records. Recovering reliable software provenance is a better first step than running an execution test against a live CMS.

Test the condition workflow without handing it a command

Build a regression plan around the operations the fix touches. Use an isolated copy with synthetic content and a test account representing the intended role. Record a normal condition selection, an empty condition, and a legitimate customized condition. Confirm that accepted inputs still return the expected content and that their saved state remains usable after reload.

Then exercise the validation boundary with inert, unexpected configuration fields. The expected result is an explicit rejection or removal before construction, according to the application’s supported behavior. Instrumentation in the isolated test can establish whether a factory was reached. There is no need to supply a shell command or an outbound callback to test that an unsupported structural key was excluded.

This proposed regression method checks the data boundary and normal feature behavior. It is not an independently executed reproduction of CVE-2026-44011, and it does not establish that every alternate route is covered. Keep the cases tied to the controller paths and extensions under review. Add a case when a separate entry path is discovered instead of treating one successful rejection as a global property.

Craft CMS maintenance checks connecting fixed branches, the serving release, valid conditions, and inert invalid-input tests.
Recommended verification workflow. The listed releases are historical fix boundaries, not current upgrade targets.

Separate account protection from runtime authority

MFA, careful role assignment, and restricting control-panel access can reduce opportunities to obtain an authenticated session. They do not change how the application interprets an accepted configuration object. A stolen editor session and a malicious authorized user are different initial scenarios, but both make the boundary between editorial operations and server execution relevant.

For a suspected incident, correlate the authenticated account and request with unexpected PHP-process behavior. Ordinary element searches can share the application surface used in the disclosed path, so a route name alone is a weak detection rule. The discriminating evidence concerns the configuration accepted and the server-side effect, where those observations were retained.

The lasting engineering lesson is unusually specific. Configuration becomes security-sensitive at the point where the framework interprets it as instructions for a live object. Verify the corrected Craft branch, inspect custom paths that cross the same boundary, and make the regression tests observe validation before construction. That produces a repair grounded in the mechanism rather than confidence borrowed from a login screen.

게시물을 공유하세요:
관련 게시물
ko_KRKorean