又一种不使用括号调用函数的方法
Yet another way to invoke functions without parentheses

原始链接: https://blog.ikaes.de/yet-another-way-to-invoke-functions-without-parentheses/

这描述了一种不使用括号即可创建并执行任意函数的 JavaScript 技术。它将 `Error.prepareStackTrace` 覆盖为 `Function`,因此访问 Error 的 stack 会从其堆栈跟踪数组触发函数创建。由于原始堆栈跟踪不是有效代码,它还控制 `Array.prototype.toString`——可以通过替换它,或通过 `Object.prototype.message` 和 `Error.prototype.toString` 进行原型污染——从而使数组变成所需的 JavaScript。最后,它通过将生成的函数赋给 `x.valueOf` 并使用 `+x` 将对象强制转换为原始值,从而在没有括号的情况下调用生成的函数。示例载荷:将 `Object.prototype.message` 设为代码,将 `Array.prototype.toString` 设为 `Error.prototype.toString`,设置 `Error.prepareStackTrace=Function`,创建 `x=new Error`,设置 `x.valueOf=x.stack`,然后执行 `+x`。

一篇来自 ikaes.de 的 Hacker News 帖子,标题为“又一种无需括号调用函数的方法”,有 24 点和 3 条评论。一条评论分享了一段使用原型操作、Error.prepareStackTrace 和一元 + 来在无括号情况下触发行为的混淆 JavaScript 代码片段,并评论 JavaScript 的奇怪能力。另一条询问最后的 `+x` 做什么,还有一条只称 JavaScript 为“cursed”。页面还包括标准 Hacker News 导航和 Y Combinator 申请广告。
相关文章

原文

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;
联系我们 contact @ memedata.com