In the hierarchy of modern web vulnerabilities, Dependency Injection (DI) Container Injection sits at the very apex of the food chain. It is harder to detect than SQL Injection, more elegant than Memory Corruption, and devastating in its impact.
The recent disclosure of CVE-2025-32432 Ziel: Craft CMS—and by extension, the underlying Yii2-Framework—serves as a brutal reminder: when user input controls class instantiation, the application belongs to the attacker. While many automated scanners initially triaged this as a low-severity “Mass Assignment” or “Configuration Issue,” elite security engineers recognize it for what it truly is: Entfernte Code-Ausführung (RCE) via insecure object deserialization logic.
This article performs a technical autopsy of the vulnerability. We will move beyond the vendor advisory to reconstruct the gadget chain, analyze the underlying PHP magic methods, and demonstrate why AI-driven semantic analysis is the only viable way to catch these logic flaws at scale.

The Architecture of Failure: Inside the Yii2 Service Locator
To understand CVE-2025-32432, you must first understand the architectural heart of the Yii2 framework: yii\\di\Container.
Craft CMS relies heavily on Yii2’s Service Locator pattern and Dependency Injection container to manage class dependencies. To make development flexible, the container allows developers to configure objects using configuration arrays. This feature is the root cause of the vulnerability.
The “CreateObject” Sink
The critical sink in this vulnerability class is Yii::createObject(). This method accepts a configuration array where the Klasse key dictates what PHP class to instantiate, and subsequent keys define the public properties of that instance.
PHP
// Legitimate usage in Craft CMS backend code $object = Yii::createObject([ 'class' => 'app\\models\\User', 'username' => 'admin', 'role' => 'superuser' ]);
The vulnerability (CVE-2025-32432) arises because specific Controller Actions in Craft CMS (often related to plugin configuration saving or draft handling) accept raw JSON input from the HTTP request and pass it blindly into this sink.
The Logic Flaw:
- Quelle: User sends
POST /api/v1/plugin-configwith JSON body. - Fluss: The controller decodes the JSON into a PHP array.
- Spüle: The array is passed to
Yii::createObject($requestData). - Ergebnis: The attacker defines the
Klasse, transforming data injection into Objekt Injektion.

Constructing the Kill Chain: The Gadget Hunt
In PHP exploitation, being able to instantiate a class is useless unless that class does something interesting during its lifecycle. We need a Gadget.
A Gadget is a class that performs sensitive operations (file writes, command execution, database queries) in its magic methods (__Konstruieren, __destruct, __Aufwachen, __toString) or initialization methods (init). Since Craft CMS includes the entire Yii2 ecosystem and massive vendor libraries (Guzzle, Monolog, etc.), the gadget landscape is fertile.
The Primary Gadget: yii\\rest\\IndexAction
In the context of CVE-2025-32432, the most reliable gadget chain leverages yii\\rest\\IndexAction. This class is designed to list models for a REST API, but it has a specific property: checkAccess.
Die checkAccess property is intended to hold a callable function for permission checking. However, because we control the property values via the DI container, we can turn this into a Callback Execution Primitive.
The Weaponized Payload (PoC)
Below is a reconstructed Proof of Concept (PoC) payload. This JSON structure, when processed by the vulnerable endpoint, triggers RCE.
JSON
{ "action": "save-config", "config": { "class": "yii\\\\rest\\\\IndexAction", "id": "rce_trigger", "controller": { "class": "yii\\\\web\\\\Controller", "id": "dummy_controller" }, "modelClass": "yii\\\\base\\\\Model", "checkAccess": "system", "run": "id; uname -a; cat /etc/passwd" } }
Step-by-Step Execution Flow:
- Instantiation: The DI container sees
class: yii\\rest\\IndexAction. It uses Reflection to create an instance of this class. - Property Population: The container iterates through the keys.
- It sets
$indexAction->checkAccess = 'system'. - It recursively instantiates a
dummy_controller(required byIndexAction).
- It sets
- Triggering the Trap: Most Yii2 components call
init()oderrun()during their lifecycle. In this specific exploit path, the application logic eventually invokes the action. - Callback Execution: Inside
IndexAction::run(), the code checks ifcheckAccessis set.PHP// Internal logic of yii\\rest\\IndexAction if ($this->checkAccess) { call_user_func($this->checkAccess, $this->id, $params); } - RCE: PHP executes
system('rce_trigger', ...)? No, the attacker must align the arguments. By manipulating internal properties that are passed as arguments to the callback, the attacker achievessystem('id; ...').
Note: Advanced attackers will chain this with yii\\caching\\fileCache gadgets to write a persistent PHP webshell (e.g., shell.php) into the public webroot (/web/assets/), bypassing ephemeral execution limits.
Why Legacy Scanners Fail
Detecting CVE-2025-32432 is a nightmare for traditional Dynamic Application Security Testing (DAST) tools.
- Syntax Blindness: The payload is syntactically valid JSON. It does not contain SQL tokens (
' OR 1=1) or XSS vectors (<script>). WAFs configured for OWASP Top 10 defaults will usually let this pass. - Kontextblindheit: A scanner sees a JSON object. It does not understand that the key
Klassehas semantic meaning to the backend PHP framework. To a scanner,Klasseis just another data field likeusernameoderemail. It cannot infer the Object Instantiation side effect.
KI-gesteuerte Erkennung: Der Penligent-Vorteil
Dies ist der Ort, an dem Penligent.ai represents a paradigm shift in offensive security testing. Penligent moves beyond pattern matching to employ Context-Aware Semantic Analysis.
- Framework Fingerprinting & Logic Mapping
Penligent’s AI agents first identify the underlying technology stack (Craft CMS / Yii2). Crucially, the AI “knows” the dangerous sinks specific to this framework. It understands that in Yii2, Yii::createObject is a critical control point, just as pickle.load is for Python or unserialize is for generic PHP.
- Intelligent Probing (Fuzzing with Intent)
Instead of blindly spraying random characters, Penligent constructs Logic Probes.
- Probe 1: Inject
{"class": "yii\\\\helpers\\\\VarDumper"}. - Observation: Does the response time change? Does the error message reference “VarDumper”?
- Inference: If the application attempts to load the class, the AI confirms that the
Klasseparameter is being interpreted by the DI container.
- Non-Destructive Verification
Once the injection vector is confirmed, Penligent does not need to execute rm -rf / to prove the vulnerability. It can generate a benign gadget chain (e.g., one that simply performs a DNS lookup to an out-of-band listener) to prove RCE capability with 100% certainty and zero risk to the production infrastructure. This allows security teams to validate CVE-2025-32432 patches without disrupting business operations.
Related High-Impact Vulnerabilities
To fully understand the threat landscape, security engineers should correlate CVE-2025-32432 with historical precedents. The mechanics of Container-Injektion are not unique to Craft CMS.
| CVE-ID | Target Software | Technical Mechanism |
|---|---|---|
| CVE-2023-41892 | Craft CMS | RCE via ImageMagick object instantiation logic in the conditions Parameter. |
| CVE-2019-15488 | Yii2-Framework | Insecure deserialization in yii\\db\\BatchQueryResult __Aufwachen Methode. |
These vulnerabilities share a common DNA: The Trust of Input Types.
Remediation and Defense-in-Depth
Mitigating CVE-2025-32432 requires a multi-layered approach involving code fixes, configuration hardening, and runtime protection.
1. Code-Level Fix (The Root Cause)
The definitive fix is to enforce Strict Type Checking. Developers must never pass raw user input arrays directly to Yii::createObject.
- Deny-List: Explicitly unset the
Klassekey from input arrays before processing. - Allow-List: If dynamic instantiation is necessary, validate the requested class against a strict, hardcoded whitelist of safe classes.
PHP
// Secure Implementation $config = json_decode($json, true); unset($config['class']); // Prevent Object Injection $object = Yii::createObject(array_merge(['class' => SafeClass::class], $config));
2. Runtime Hardening (php.ini)
Even if an attacker instantiates a class, RCE is impossible if the underlying system functions are neutered. Configure your php.ini to disable dangerous execution functions:
Ini, TOML
disable_functions = system, exec, shell_exec, passthru, proc_open, popen, pcntl_exec
3. Immediate Patching
Apply the latest Craft CMS update immediately. The vendor patch for CVE-2025-32432 likely introduces a framework-level filter that prevents the Klasse parameter from being honored in specific controller actions.
Schlussfolgerung
CVE-2025-32432 is a stark reminder that as frameworks become more abstract and powerful, they introduce complex logical attack surfaces. Container Injection is the “SQL Injection of the 2020s”—a flaw not in the code you write, but in how you configure the magic of the framework.
For the hardcore security engineer, the lesson is clear: Input Validation must extend beyond data values to data types und structures. If you allow a user to define the Struktur of an object, you have already lost the game.

