`
ziyuewang
  • 浏览: 39356 次
  • 性别: Icon_minigender_2
  • 来自: 济南
社区版块
存档分类
最新评论

Javascript 看看黑客怎么写的

阅读更多
在2011年的BlackHat DC 2011大会上Ryan Barnett给出了一段关于XSS的示例javascript代码:

($=[$=[]][(__=!$+$)[_=-~-~-~$]+({}+$)[_/_]+($$=($_=!''+$)[_/_]+$_[+$])])()[__[_/_]+__[_+~$]+$_[_]+$$](_/_)


这是一段完全合法的javascript代码,效果相当于alert(1)。它可以在大部分浏览器上运行。(虽然目前我测试过手头的浏览器都能运行,但理论上不能保证所有浏览器都能正确运行,原因见下文)

这段代码的好处(对于黑客)是,它不包含任何字符或数字,可以逃过某些过滤器的检查。比如说,如果假定一个AJAX请求将返回一个只包含数字的JSON,于是很可能会简单判断了一下其中不含字母就直接eval了,结果给黑客们留下了后门。上面的代码功能很简单,只是alert(1),但使用同样的原理,完全可以干出更复杂的事,例如alert(document.cookie)。更重要的是,这段代码再一次提醒我,黑客的想象力是无限的……正如Ryan Barnett的演讲标题:"XSS:The only rule is no rule"。

那么这段代码是如何工作的呢?

我们可以把它分为两个部分来理解:
第一部分:

($=[$=[]][(__=!$+$)[_=-~-~-~$]+({}+$)[_/_]+($$=($_=!''+$)[_/_]+$_[+$])])() 


第二部分:

[__[_/_]+__[_+~$]+$_[_]+$$](_/_) 


其中第一部分是核心,我们首先对它进行分析,先缩进一下:

($= [$=[]][  
        (__=!$+$)[_=-~-~-~$] +  
        ({}+$)[_/_] +  
        ($$= ($_=!''+$)[_/_] + $_[+$])  
    ]  
)()  




显然,最外层是(...)()形式的函数调用,我们需要看看这里究竟调用了什么函数,返回了什么。下一步,我们把原来代码中赋值表达式提取出来,将其改写为以下等价形式:

$ = []; //1  
__ = !$+$; //2  
_ = -~-~-~$; //3  
$_=!''+$;  //4  
$$ = $_[_/_] + $_[+$];  //5  
  
$= [$][  
        __[_] +  //6  
        ({}+$)[_/_] +  //7  
        $$  //8  
    ];  //9  
  
$(); //10  



现在来一行行看:
1. $先赋值为一个空数组  (后面会被覆盖)

2. __ = ![] + [] = false + [] = "false"  这里利用了javascript运算的强制类型转换特性。首先空数组是一个非null值,因此![]的结果是false(布尔型)。在计算false + []时,由于数组对象无法与其他值相加,在加法之前会先做一个toString的转换,空数组的toString就是"",因此事实上在计算false + ""。这时false被自动转换为字符串。最终结果是"false"+"" = "false"。  **换句话说,在$为空数组时,使用 “+$”的方式可以将任何一个值转为字符串**

3. 在计算~[]时,~需要一个数字操作数,空数组无法直接转换为数字,则作为0处理。因此~[] = ~0 = -1


参考:  
~3 = -4  
~[3] = -4  
~[3,2] = -1  (无法转为数字)  
~"3" = -4  
~"abc" = -1  


因此: _ = -~-~-~[] = -~-~-(-1) = -~-~1 = -~-(-2) = -~2 = -(-3) = 3  理论上,可以用这种方式得出1-9所有数字

4. !''是true,使用+$将其变为字符串 "true"

5. 这里需要注意的是,之前一直用“值+[]”来获得“值”的字符串形式。而“+[]”则是0(正号导致[]被自动转换为数值0)。因此:$$ = "true"[3/3] + "true"[+[]] = "true"[1] + "true"[0] = "rt"

6. __[_] = "false"[3] = "s"

7. ({} + [])导致空对象{}被转换为字符串"[object Object]", 因此({}+$)[_/_] = "[object Object]"[1] = "o"

9. 这里把$覆盖为 [[]]["s"+"o"+"rt"]。注意这里[[]]本身是一个包含空数组的数组,其实对这一步来说,任何一个数组都没有关系(不一定要是嵌套数组),但作者巧妙地把$的首次赋值式放在了数组内部,使代码更为紧凑。最终结果是,$ = [[]]["sort"] = [[]].sort = Array.prototype.sort。

10. 调用$(),作为整个表达式最终的取值。需要注意,$是全局范围的,是window的一个属性,相当于window.$。而Array.prototype.sort会返回this。对于window.$来说,this就是window。因此,整个第一部分的值,就是window本身!当然,这个过程的正确运作依赖于当前浏览器的Array.prototype.sort实现能对this为window的情况容错。

通过第一部分,我们已经获得将任何值转换为字符串的简单方法,并能产生任意的数值,理论上就可以从javascript的取值系统中提取出大部分字母(不知道是不是全部,需要考证)。并且,我们获取到了window的引用。下面就可以开始上下其手,为所欲为了。木哈哈哈哈哈!

可以看出,上面的第10步是与浏览器的具体实现相关的,因此也存在着某些浏览器下需要对代码作出修改的可能。

现在看第二部分,事实上已经非常明朗了,唯一需要注意的是,现在$是一个函数,因此~$ = ~0 (无法直接转换为数字则作为0处理) = -1。

[__[_/_]+__[_+~$]+$_[_]+$$](_/_) = ["false"[1]+"false"[3+(-1)]+"true"[3]+"rt"](1) = ["a"+"l"+"e"+"rt"](1)  


所以,整条式子相当于:

window["alert"](1) 


最后只想再感慨一次:黑客的想象力是无限的。理解代码并不难,问题是一开始时他们是怎么能想出来的 ...


备注 : 本文属于转载
分享到:
评论
16 楼 nianshi 2011-08-26  
简单就是美
15 楼 youjianbo_han_87 2011-04-26  
个人认为,简单就是美,就算是黑客
14 楼 lx_corn 2011-04-26  
我说怎么觉得眼熟
13 楼 axhack 2011-04-26  
看内容,不是看谁转载的早与晚。
反正我是投一次看见这文章,涨见识了。
12 楼 telyy123 2011-04-26  
转别人帖子,注明来源
11 楼 renwolang521 2011-04-26  
发表时间 2011-03-18
http://www.iteye.com/topic/947149

这时间也不长吧,你的和人家唯一的不同就是你的是java代码,人家的是javascript代码,况且转载 也要注明 出处

发个完全重复的 真没意思
10 楼 digfog 2011-04-26  
真的是很NB
9 楼 ziyuewang 2011-04-25  
我们的共同的目的是学习!哈哈哈!
8 楼 qianye 2011-04-25  
你不要老转载别人的东西好不?
7 楼 junfengcode 2011-04-25  
哥们最近很活跃,js的魅力确实不小,我也渐渐的爱上界面开发了
6 楼 dondon 2011-04-25  
先不说别的,人家能想到,就是比你自己牛,既然比自己牛一点,就应该学习啊。
5 楼 云天水瓶 2011-04-25  
不久前见过
4 楼 feiyan35488 2011-04-25  
早就发过了
3 楼 super88home 2011-04-25  
tianshiyeben 写道
加密过的js   嘿嘿  黑客应该没有这么高深吧

黑客比这高深多了
2 楼 tianshiyeben 2011-04-25  
加密过的js   嘿嘿  黑客应该没有这么高深吧
1 楼 lib 2011-04-25  
<p>哥们,这帖子早就有人发过了。</p>
<p> </p>
<p>看看这个帖子:<a href="http://www.iteye.com/topic/947149">http://www.iteye.com/topic/947149</a></p>

相关推荐

Global site tag (gtag.js) - Google Analytics