【问题标题】:Javascript window object, window+'', what does this code do [closed]Javascript窗口对象,window+'',这段代码做了什么[关闭]
【发布时间】:2020-10-18 18:29:04
【问题描述】:

我正在尝试解决一个 portswigger 实验室 (https://portswigger.net/web-security/cross-site-scripting/contexts/lab-javascript-url-some-characters-blocked),但我不明白为什么当省略表达式 window+'' 时这段代码没有弹出警报:

x=x=>{onerror=alert; throw 1337},toString=x,window+''

非常感谢对这段代码 sn-p 的完整解释,谢谢。

【问题讨论】:

  • 有登录表单....
  • 链接没有带我回答你的问题...

标签: javascript


【解决方案1】:

首先,代码使用comma operator(另见What does a comma do in JavaScript expressions?)。逗号运算符的作用是允许您评估多个表达式。特别是在这种情况下,您有三个:

   x=x=>{onerror=alert; throw 1337},toString=x,window+''
// ^______________________________^ ^________^ ^_______^
//                 1                     2         3

让我们一一检查:

关于隐式全局变量的简要说明

这将与以下大部分内容相关,因此我想先澄清一下。任何时候您分配给您尚未使用varletconst 声明的任何名称时,它都会隐式分配给全局对象上的属性。在浏览器中,全局对象是window,所以任何隐式全局对象都会去那里:

console.log("before assignment");
console.log("'foo' in window:", 'foo' in window);
console.log("window.foo:", window.foo);

foo = 42;

console.log("after assignment");
console.log("'foo' in window:", 'foo' in window);
console.log("window.foo:", window.foo);

箭头函数

x=x=>{onerror=alert; throw 1337}

定义

这将创建一个新的箭头函数并将其分配给x。由于没有变量声明,x 将是一个隐式全局,因此附加到window。这不是非常有用 - 它可能是为了保存一些字符。该函数还接受一个名为x 的参数,但它不做任何事情。同样,没有任何用处 - 保存单个字符,否则需要将其定义为 ()=>

主体部分 1

更有趣的是该函数的作用。

onerror=alert

首先它将onerror 分配给alert。这两个都是global error handlerglobal alert() function 作为引用传递。因此,任何时候发生 any 错误,它只会显示警报:

window.onerror = alert;

JSON.parse("{"); // parsing error

有关如何使用函数引用的更多信息,请参阅 What is the difference between a function call and function reference?Difference of calling a function with and without parentheses in JavaScript。简而言之,如果将函数分配给处理程序,则调用该处理程序实际上会运行该函数。

身体部分 2

然后发生的事情是箭头函数抛出throw 1337 的错误。在 JavaScript 中,您可以分配要抛出的任何值,因此它是否是错误并不重要。因此,抛出一个数字是有效的。抛出的值并不真正相关,因为重要的是抛出错误。由于函数的第一部分,这个throw 语句将触发全局错误处理程序。这是一个演示(格式化):

x = x => {
  onerror = alert;
  throw 1337
}

x();

到目前为止,一切都很好,但这不是在代码中调用函数的方式。让我们进入下一部分。

覆盖toString

toString=x

这部分将覆盖window 上的toString 方法并将其更改为x 函数。因此,任何时候您显式或隐式window 转换为字符串,它将改为执行x

x = x => {
  onerror = alert;
  throw 1337
}

toString = x;

window.toString();

window 转换为字符串

在 JavaScript 中,当您尝试将任何值与字符串连接时,该值也将被隐式转换为字符串。这通常通过调用toString() 方法来完成:

const value1 = { "foo": 42 };
const value2 = { 
  "foo": 42,
  toString() {
    return `foo is ${this.foo}`;
  }
};

const value3 = { 
  "foo": 42,
  toString() {
    return "Hello world";
  }
};

console.log(value1 + ""); //default `toString()` method of objects
console.log(value2 + "");
console.log(value3 + "");

同样的事情发生在代码的最后部分:

window+''

这将:

  1. 触发到字符串的转换,
  2. window 上调用toString 方法,该方法
  3. x使用toString=x覆盖,
  4. 改为调用x 函数,该函数
  5. 将全局错误处理程序设置为 alert (onerror=alert) and immediately throws an error (throw 1337`),即
  6. 调用全局错误处理程序

为什么省略 window+'' 不会引发错误

希望从上面清楚,但要直接解决它 - 需要该代码来触发之前定义的整个反应链。

为了清楚起见,这是带有解释和格式的完整代码:

//create a function
window.x = x => {
  onerror = alert; //changes the global error handler
  throw 1337       //throws an error to trigger the error handler
};

//overwrite the `toString` method of `window` so it always throws an error
window.toString = window.x; 

//implicitly call `window.toString()` by performing a string concatenation
window + '';

【讨论】:

  • 我爱你!非常感谢!
猜你喜欢
  • 2013-01-24
  • 1970-01-01
  • 1970-01-01
  • 2014-11-12
  • 1970-01-01
  • 2022-06-28
  • 1970-01-01
  • 1970-01-01
  • 2018-08-09
相关资源
最近更新 更多