2010-01-20 78 views
11

我有兴趣了解JavaScript的内部结构。我尝试阅读SpiderMonkeyRhino的源代码,但将头部缠绕起来相当复杂。为什么(![] + [])[+ !! [] + []]产生“a”

我想问的原因是:为什么像

  • (![]+[])[+!![]+[]]农产品"a"
  • (Å=[],[µ=!Å+Å][µ[È=++Å+Å+Å]+({}+Å)[Ç=!!Å+µ,ª=Ç[Å]+Ç[+!Å],Å]+ª])()[µ[Å]+µ[Å+Å]+Ç[È]+ª](Å)产生alert(1)

来源:http://sla.ckers.org/forum/read.php?24,32930,page=1

在这个论坛上还有很多关于JavaScript古怪的例子,我想知道它是如何从编程的角度来看web应用程序的安全性。

+0

如果你有兴趣在语言是如何工作的,没有什么比写一个编译器为它自己 - 这基本上都会教你的语言,它的内部。 – Chii 2010-01-20 09:50:26

+0

感谢您的回复。我知道Javascript做了一些魔术,但它所做的一些事情是危险的...... – prafulfillment 2010-01-20 18:20:07

回答

12

为什么(![]+[])[+!![]+[]]产生 “一”

一步一步:(![]+[])[+!![]+[]]:这是解析。第一位已由artemb解释:[]是一个数组。否定它,![]评估为布尔值,false - 这就是!如何应用于非null或未定义的东西。再如artemb指出的,附加+[]强制将布尔值转换为字符串。这是因为+是一个字符串连接运算符。然后将布尔型false转换为其字符串表示形式"false"

然后,第二位,[+!![]+[]]。首先,外部[]用于将前面的字符串作为一个字符数组来处理,我们只是将这个字符串等同于"false"。通过在[]中放入一个整数索引,可以在特定索引处获得该字符。所以剩下的是+!![]+[] 这包括4件:+,!![],+[]。首先对!![]进行评估。我们已经看到![]是一个布尔型false,因此预先计划另一个!否定它,并产生true。接下来会发生什么事是,在+!![]+得到应用,并通过应用+它的布尔true转换成数字表示,这是1(所以+true1)下面的+[]再次从1产生"1"但使一个字符串它没有任何意义,较短的表达式(![]+[])[+!![]]已经产生了a。追加+[]也不会伤害,结果表达式只是["1"]而不是[1]。我的直觉是,当[]应用到阵列中,无论是[]内将强制转换为数字,这对于"1"将再次给1。因此无论哪种方式,+!![]+[]评估到1,使最终表达式:"false"[1]这就是说:从字符串"false"给我索引1的字符,因为默认情况下,数组在javascript中开始于0,这是"false"的第二个字符,和a

16

如果你想了解为什么这些奇怪的表达式就像他们那样工作,你可以打开萤火虫控制台并试验自己。我做到了,![]false,!![]true,将数组添加到布尔值(false+[]true+[])生成此值的字符串版本(false+[]="false")。

这样表达归结为:

"false"["1"] 

这显然是 “一”

+4

这是如何明显? – medopal 2010-01-20 10:16:41

+0

很明显,如果你有足够的时间和创造力,你可以使用这个有限的字符串连接和索引访问器来创建任意字符串。 – 2010-01-20 10:21:15

+0

@medopal也许不完全明显:) 它是字母 “a” 中的字符串 “假”( 'F'= 0, 'A'= 1时, 'L'= 2的索引, 'S'= 3 ,'e'= 4)。 – 2010-01-20 10:51:27

1

我建议您获取和阅读:

  • ECMAScript标准(ECMA 262),第5版本
  • Adob​​e文档称为“AVM 2概述”,它解释了AVM2虚拟机的体系结构,其中Adobe Flash及其ActionScript 跑。
2

为什么[+ !! [] + []生产的 “一”

  1. !expr([] + []!) - 在EXPR调用ToBoolean和翻转布尔值。换句话说,truthy值(如空数组)在与not运算符一起使用时将产生false。
  2. a + b - 两个表达式都通过内部ToPrimitive运行。如果结果值是一个字符串,则执行字符串连接。否则,原语通过ToNumber运行并添加。 ToPrimitive for objects(包含数组)将尝试toString和valueOf。 Array.prototype.toString充当没有参数的调用连接。因此,![] + [] = false + "" = "false"
  3. !![] == true,一元加号操作者转换表达式的数字,所以1。再次,数组转换为"",所以+!![]+[] == "1"
  4. 表达归结为("false")["1"] == "a"

其它表达可以以类似的方式可以归结。它使用unicode字符串来解决它,并且它更长,但就像“解析”一样简单。

相关问题