Javascript 函数自动嵌入到参数 运行 中?

Javascript functions embedded in arguments run automatically?

我正在研究防御各种类型的攻击,但我发现了一种我不太了解的攻击。

我有以下 html:

<body onload="foo(''/alert(/Gotcha/)/'');">
<script>
   function foo(){
      alert("Inside Foo");
   }
</script>
</body>
</html>

如果你 运行 这样做,你会看到一个提示“/Gotcha/”,紧接着是一个提示 "Inside Foo"。

这是怎么回事?为什么参数中的警报(foo 甚至没有)运行ning?

而且,如果我删除参数中的任何斜杠或单引号,它就不起作用。

如果我把它改成

<body onload="foo('/alert(/Gotcha/)/');">

我得到的只是"Inside Foo"。

如果我把它改成

<body onload="foo('/alert(Gotcha)/');">

或删除任何 /s 我什么也没得到。

' 和 / 的作用是什么?

foo 调用中的参数运行的原因是因为它被解释为 JavaScript。您在 foo(''/alert(/Gotcha/)/'' 中传递的参数本质上是 2 个字符串,在它们中间是一个 alert 调用。

函数参数全部计算在调用函数之前。所以当你写:

foo(alert('/Gotcha/'));

它首先计算 alert('/Gotcha/'),这会导致显示 /Gotcha/。然后将alert()的return值作为参数传递给foo()foo() 忽略它的参数,但这对第一步无关紧要。

当你把它改成

foo('/alert(/Gotcha/)/');

那么参数是一个文字字符串,而不是一个函数调用。所以评估它只是 returns 字符串内容,它不会调用 alert() 函数。

我看不出有什么理由

<body onload="foo('/alert(Gotcha)/');">

的行为与

有任何不同
<body onload="foo('/alert(/Gotcha/)/');">

所以我怀疑您的实际代码有错别字,您没有在此处复制。检查您的 Javascript 控制台以获取语法错误消息。

这里有一个复杂的表达式,所以让我们分解一下:

foo(''/alert(/Gotcha/)/'');

  1. JS 将此解释为调用函数 foo 并以 ''/alert(/Gotcha/)/'' 作为参数(JS 中的函数没有硬参数,您可以发送任意数量的参数,甚至如果函数声明没有指定它们)
  2. 参数被评估为字符串''后跟除法字符/,然后是alert函数,然后是另一个除法和另一个空字符串
  3. 评估警报的参数,因为它不是字符串,而是正则表达式,顺便说一句,字符串表示与输入正则表达式字符串相同
  4. alert 使用正则表达式的字符串表示形式执行,以评估 foo 的参数,整个参数表达式的结果是 NaN,因为字符串不是整除这并不重要,因为函数 foo 不使用它
  5. 函数foo被执行。

问:"Javascript functions embedded in arguments run automatically?"


A: 与函数参数无关。 foo 函数只是为了增加已经混淆的表达式的混淆。这是编写等价于以下内容的一种简单的复杂方法:

onload="alert(/Gotcha/)"

想要提醒 /Gotcha/ regex literal 的内容。

body onload 赋值字符串中提供的正则表达式文字只是同一字符串中提供的警报函数的被动值,与那里发生的事情没有任何关系。

其他一切都只是一种巧妙的方式来掩盖简单的赋值,例如上面给出的 onload="alert(/Gotcha/)" 行代码。

唯一让它起作用的是内联事件分配是需要评估才能执行的字符串。

因此eval( ''/alert(/Gotcha/)/'' )也会这样做。或者将其全部恢复为原始形式:eval( "foo(''/alert(/Gotcha/)/'');" ).

所以是的,可以执行内联分配给元素事件的任何类型的字符串内容。但是,setTimeout("foo(''/alert(/Gotcha/)/'');", 1000) 也能做同样的事情。

所以,"no"它与函数参数无关,而是与将字符串内容解析为文档正文元素的内联事件


编辑:

在包含 html 的字符串上内联 JavaScript 是(出于上面解释的 Gotcha 警报为何起作用的原因)最危险的代码注入,无需用户输入。这是因为图像元素可以处理 onerror 事件,可以执行任意代码块,如:

<img 
    src="http://Idontexist.com/wrongfolder/missingimage.jpg" 
    onerror="your arbitrary, but well written (malicious) code here!"
>