yet another way to invoke functions without parentheses

i found yet another way to invoke arbitrary functions in javascript without using parentheses

this payload works by overwriting the prepareStackTrace function of the Error object to generate arbitrary functions. it is usually used to format stack traces and is invoked when the attribute stack of an error is accessed.

the parameters of this function are the error and "a structured representation of the stack" , which is just an array of the code positions. it has the same function signature the Function constructor which is used to generate javascript functions, as long as the second argument is valid javascript code.

if we try to invoke the function which was generated using this method, we get a syntax error. it is to be expected, because a stack trace is not a valid javascript code, but an Array of code positions

in order to make the payload work, we need to control the output of the Array.prototype.toString() function such that it returns our desired javascript payload. this can be done in two ways

first we can simply overwrite it with a constant function which returns the payload

or we can use prototype pollution to sneak our payload into another function, and then overwrite the Array prototype. i found that we can stay in the Error realm and use its toString function which can be manipulated by polluting the Object.prototype.message variable. i am sure there are more ways to achieve this.

now if we put everything together - the function generation using the prepareStackTrace function and way to convert arrays into arbitrary strings, we can generate arbitrary javascript functions

last thing we have to do is to invoke our new function. luckily there are many ways to do so and i chose the valueOf trick. it works by overwriting the default valueOf function of our object and then invoking it as a primitive. alternatively, we can use toString and then concatenate the object with a string.

the final payload is as follows. feel free to try it out in the browser console.

Object.prototype.message='alert\x281337\x29';Array.prototype.toString=Error.prototype.toString;Error.prepareStackTrace = Function;const x = new Error;x.valueOf=x.stack;+x;