CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2023-41892

Craft CMS RCE: The Art of Unauthenticated Object Injection

Alon Barad
Alon Barad
Software Engineer

Feb 26, 2026·6 min read·57 visits

Executive Summary (TL;DR)

Unauthenticated attackers can send a crafted HTTP POST request to Craft CMS versions 4.0.0 through 4.4.14 to execute arbitrary PHP code. This exploits a flaw in how the CMS handles user-supplied configuration arrays, turning a standard feature into a remote shell generator.

A critical remote code execution vulnerability in Craft CMS allows unauthenticated attackers to hijack the application's object instantiation logic. By manipulating the `ConditionsController`, attackers can trick the underlying Yii2 framework into creating arbitrary PHP objects with malicious configurations, leading to immediate server compromise via Guzzle or Imagick gadgets.

The Hook: Crafting Chaos

Craft CMS is the darling of the agency world. It’s slick, it’s flexible, and it’s built on top of the Yii2 framework. For the uninitiated, Yii2 is a powerful beast that relies heavily on "magic"—specifically, a dependency injection container that can instantiate classes and configure their properties on the fly using arrays. It’s a developer’s dream: define a class, throw an array of settings at it, and the framework handles the rest.

But here’s the thing about magic: if you let the wrong person wave the wand, things explode. In September 2023, researchers discovered that Craft CMS was a little too generous with who held the wand. Specifically, the ConditionsController allowed unauthenticated users to pass arbitrary configuration arrays directly into this object creation engine.

This isn't your standard buffer overflow or a forgotten SQL injection. This is Object Injection via Configuration. It’s the architectural equivalent of letting a stranger walk into a car factory, hand the foreman a blueprint for a tank, and having the factory build it without asking questions. The result? A CVSS 10.0 vulnerability that allows anyone on the internet to execute code on your server as www-data.

The Flaw: Trusting the Untrustworthy

The vulnerability lives in craft\controllers\ConditionsController.php. This controller is designed to handle dynamic conditions for content filtering. To do this, it needs to accept configuration data from the user to know what conditions to apply. So far, so standard.

The fatal mistake was in the beforeAction method. In Yii2, beforeAction runs before the main controller action. Craft CMS developers decided to process the request parameters here. They took the raw POST data, specifically a parameter named config, decoded it from JSON, and then—here is the kicker—passed it straight into the object creation service.

Because Yii2’s BaseObject allows for "Mass Assignment" (setting properties based on array keys), an attacker can control every public property of the class they ask to create. Even worse, Yii2 supports "behaviors" (keys starting with as ) and "events" (keys starting with on ). This means an attacker isn't just setting simple strings or integers; they can attach entire behavior classes or define event handlers that execute arbitrary PHP code.

The Code: The Smoking Gun

Let's look at the crime scene. In the vulnerable versions (<= 4.4.14), the code looked something like this:

// Vulnerable code in ConditionsController
public function beforeAction($action)
{
    // ... various checks ...
    
    // 1. Take user input blindly
    $config = $this->request->getBodyParam('config');
    
    // 2. If it looks like JSON, decode it
    if (is_string($config) && Json::isJson($config)) {
        $config = Json::decode($config);
    }
 
    // 3. Create the object using the user's config
    $condition = Craft::createObject($config);
    
    // ...
}

See the problem? There is zero validation on $config. If I send {"class": "\Evil\Class", "property": "bad_value"}, the application happily creates \Evil\Class.

The fix in version 4.4.15 was a multi-step remediation. First, they ensured the configuration is "cleansed" of dangerous keys like on (events) and as (behaviors). Second, they strictly typed the input. Third, and perhaps most importantly, they enforced authentication checks before this logic runs.

// Patched code
public function beforeAction($action)
{
    // Enforce permissions first!
    $this->requireCpRequest();
    
    // Sanitize the config
    $config = Craft::$app->getRequest()->getBodyParam('config');
    // ... decoding logic ...
    
    // Cleanse dangerous keys
    $config = Component::cleanseConfig($config);
    
    return parent::beforeAction($action);
}

The Exploit: Weaponizing Garbage Collection

So we can create objects. Great. But how do we get a shell? We need a "gadget"—a class already present in the codebase that does something dangerous. Since Craft CMS includes Guzzle (a popular HTTP client), we have a perfect candidate: \GuzzleHttp\Psr7\FnStream.

This class is a wrapper for PHP streams. It has a magic method, __destruct(), which is called when the object is destroyed (garbage collected) at the end of the script execution. The __destruct method in FnStream checks if a custom close function (_fn_close) is defined and, if so, executes it.

Here is the attack chain:

  1. Instantiate: Tell the controller to create a \GuzzleHttp\Psr7\FnStream object.
  2. Configure: Set the private property _fn_close to a string representing a PHP function, like phpinfo or system.
  3. Wait: The request finishes. PHP cleans up memory. The FnStream object is destroyed.
  4. Boom: __destruct() fires, calls call_user_func($this->_fn_close), and our code runs.

The payload looks remarkably simple for such a devastating exploit. A standard Nuclei template or Python script sends a POST request to index.php with:

{
  "action": "conditions/render",
  "config": {
    "class": "\\GuzzleHttp\\Psr7\\FnStream",
    "__construct()": [{"close": null}],
    "_fn_close": "phpinfo"
  }
}

If you see the PHP configuration page in the response, you own the server.

The Impact: Game Over

This is a full unauthenticated RCE. The attacker runs as the web server user (usually www-data). From here, the possibilities are endless and terrifying.

First, they can read your .env file, stealing your database credentials, AWS keys, and the CRAFT_SECURITY_KEY. With the database credentials, they can dump your entire user table, including hashed passwords. With the security key, they can forge session cookies or encrypt malicious payloads to be executed elsewhere.

Second, they can modify the CMS itself. They could inject a persistent backdoor into index.php that survives updates, or install a web shell deep in the vendor directory where you're unlikely to look. Ransomware gangs love these vulnerabilities because they are easy to automate. One script can scan thousands of servers, drop a cryptominer or encrypt the filesystem, and move on.

The Fix: Shutting the Door

If you are running Craft CMS 4.0.x through 4.4.14, you are vulnerable. Stop reading and update to 4.4.15 or higher immediately. The patch introduces strict validation on the config parameter, stripping out the magic keys that allowed the exploit to work.

After patching, you aren't done. You must assume you were compromised if your server was exposed to the internet.

  1. Rotate Keys: Change your CRAFT_SECURITY_KEY and any API keys stored in your .env file.
  2. Check Logs: Look for POST requests to index.php containing action=conditions/render or suspicious JSON payloads involving FnStream or Imagick.
  3. Verify Integrity: If possible, nuke the vendor folder and reinstall dependencies (composer install) to ensure no backdoors were planted in library files.

Official Patches

Craft CMSOfficial Changelog for 4.4.15

Fix Analysis (2)

Technical Appendix

CVSS Score
10.0/ 10
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:L
EPSS Probability
93.94%
Top 0% most exploited

Affected Systems

Craft CMS 4.0.0-RC1 through 4.4.14

Affected Versions Detail

Product
Affected Versions
Fixed Version
Craft CMS
Pixel & Tonic
>= 4.0.0-RC1, <= 4.4.144.4.15
AttributeDetail
CWE IDCWE-94 (Code Injection)
CVSS Score10.0 (Critical)
Attack VectorNetwork (HTTP POST)
EPSS Score0.93942 (99.88%)
Exploit StatusActive / Weaponized
Gadget UsedGuzzleHttp\Psr7\FnStream

MITRE ATT&CK Mapping

T1059Command and Scripting Interpreter
Execution
T1190Exploit Public-Facing Application
Initial Access
CWE-94
Improper Control of Generation of Code ('Code Injection')

Known Exploits & Detection

MetasploitMetasploit module exploiting the unauthenticated RCE via Guzzle gadget
GitHubPython PoC for Craft CMS RCE

Vulnerability Timeline

Patch released in Craft CMS 4.4.15
2023-07-03
CVE-2023-41892 assigned
2023-09-13
Full technical analysis and PoC published
2023-09-14
Metasploit module released
2023-12-14

References & Sources

  • [1]Calif.io Deep Dive Analysis
  • [2]GitHub Security Advisory

More Reports

•2 days ago•GHSA-7PPR-R889-MCF2
7.5

GHSA-7PPR-R889-MCF2: Unbounded WebSocket Message Aggregation in http4s-blaze-server leads to Denial of Service

An uncontrolled resource consumption vulnerability exists in the Scala-based http4s-blaze-server package of the http4s/blaze library. The vulnerability allows remote, unauthenticated attackers to cause an Out of Memory Error (OOM) and JVM crash by streaming a continuous sequence of small or empty WebSocket continuation frames with the FIN bit set to 0. This bypasses typical payload size checks because of the JVM's per-object allocation overhead, leading to rapid heap exhaustion with minimal network bandwidth.

Alon Barad
Alon Barad
7 views•5 min read
•2 days ago•GHSA-95CV-R8X4-VH75
7.6

GHSA-95cv-r8x4-vh75: Path Traversal Vulnerability in OpenList Batch Rename Handler

A critical path traversal vulnerability has been identified in the OpenList Go-based backend package. The vulnerability exists within the batch rename handler because the application does not validate the source filename parameter before constructing filesystems paths. This omission allows authenticated users to escape their designated directory and rename files in sibling paths.

Amit Schendel
Amit Schendel
9 views•7 min read
•2 days ago•GHSA-P6PH-3JX2-3337
4.3

GHSA-P6PH-3JX2-3337: Horizontal Privilege Escalation and Metadata Information Disclosure via Bleve Search in OpenList

OpenList version 4.2.3 and prior is vulnerable to an authorization bypass and metadata leakage. When configured with the Bleve search engine backend, OpenList fails to perform separator-aware path matching when validating tenant containment. This allows authenticated users to access sibling directories sharing similar name prefixes. Furthermore, the search backend returns unfiltered global result counts, leaking existence verification data of unauthorized files via side-channel analysis.

Amit Schendel
Amit Schendel
8 views•5 min read
•2 days ago•GHSA-86CX-WWF4-PHQ4
6.5

GHSA-86cx-wwf4-phq4: Path Prefix Confusion Authorization Bypass in OpenList

An authorization bypass vulnerability in OpenList version 4.2.3 and below allows authenticated users to read arbitrary files outside of their designated base directories due to an insecure path prefix check using Go's standard strings.HasPrefix function.

Amit Schendel
Amit Schendel
7 views•6 min read
•2 days ago•CVE-2026-16584
7.0

CVE-2026-16584: Security Policy Bypass in AWS API MCP Server via Startup Initialization Failure

A security policy bypass vulnerability exists in the AWS API MCP Server (awslabs-aws-api-mcp-server) from version 0.2.13 through 1.3.46. When the server fails to load the read-only operations index during startup (due to transient network failures, file permission issues, or other exceptions), it logs a warning but continues running in an insecure, degraded state. Under this condition, the security policy engine fails open, silently skipping all subsequent security checks and consent prompts for the lifetime of the process. This permits unauthorized mutating AWS CLI commands to execute via indirect prompt injection attacks.

Amit Schendel
Amit Schendel
12 views•7 min read
•2 days ago•GHSA-6V4M-FW66-8R4X
6.5

GHSA-6V4M-FW66-8R4X: Path Disclosure and Shell Expansion Bypass in Shescape

An incomplete escaping vulnerability in the npm package 'shescape' allows unauthenticated users to trigger dynamic shell expansions, absolute path disclosure, and command block break-outs on Unix and Windows systems.

Alon Barad
Alon Barad
6 views•7 min read