在2011年的BlackHat DC 2011大会上Ryan Barnett给出了一段关于XSS的示例java script 代码:

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

彩蛋爆料直击现场

这是一段完全合法的java script 代码,效果相当于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" 这里利用了java script 运算的强制类型转换特性。首先空数组是一个非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的情况容错。

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

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

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

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

所以,整条式子相当于:

window["alert"](1)

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

Java script 看看黑客怎么写的的更多相关文章

  1. Java Script 编码规范【转】

    Java Script 编码规范 以下文档大多来自: Google JavaScript 编码规范指南 Idiomatic 风格 参考规范 ECMAScript 5.1 注解版 EcmaScript ...

  2. Java Script 中 ==(Equal) 和 === (Identity Equal) 的区别和比较算法逻辑

    判断两个变量是否相等在任何编程语言中都是非常重要的功能. JavaScript 提供了 == 和 === 两种判断两个变量是否相等的运算符,但我们开始学习的时候 JavaScript 的时候,就被一遍 ...

  3. Java Script 简介

    Java Script 简介 JavaScript 是世界上最流行的编程语言. 这门语言可用于 HTML 和 web,更可广泛用于服务器.PC.笔记本电脑.平板电脑和智能手机等设备.JavaScrip ...

  4. Java Script注意事项

    1.HTML中,打错标点符号 或输入格式不对(多输等号 或少加括号等) 会导致字体颜色不对劲 2.写Java Script时通常的做法是把函数放入 <head> 部分中,或者放在页面底部. ...

  5. Java Script 学习笔记 -- 基础知识

    Java script 概述 java Script 的简介 JavaScript一种直译式脚本语言,是一种动态类型.弱类型.基于原型的语言,内置支持类型.它的解释器被称为JavaScript引擎,为 ...

  6. Java Script的认识

     JavaScript的诞生 1.Java Script诞生于1995年.由Netscape(网景公司)的程序员Brendan Eich(布兰登)与Sun公司联手开发一门脚本语言,  最初名字叫做Mo ...

  7. java script第一篇(按钮全选的实现)

    今天刚学了java script,记录下学习新知识的点滴.以下是操作步骤.鉴于我是初级者,如有错误,恳请读者指正.万分谢谢. 1.新建一个文档(用NotePad软件,为了使得在浏览器中打开不是乱码,在 ...

  8. Java script基础

    Java script基础 Js的每个语句后面都要有分号. <script  type="text/java script">所有JS内容</script> ...

  9. ruby开源项目之Octopress:像黑客一样写博客(zhuan)

    ruby开源项目之Octopress:像黑客一样写博客 百度权重查询 词库网 网站监控 服务器监控 SEO监控 Swift编程语言教程 今年一直推荐的一种写作方式.markdown语法快速成文,git ...

随机推荐

  1. Java入门到精通——调错篇之解决MyEclipse 输入注册码后:Enter or update your subscription information.问题

    这几天,我用MyEclipse做例子的时候总是出现下面图上面的提示: 不用看就是注册码到期了要注册.找了好几个注册码总是出现Enter or update your subscription info ...

  2. 我爱我家:我为什么选择AppCan?

    10年前,说起手机,大家联想到的词大概是:电话.短信.QQ.拍照,以及贪吃蛇等有限的几个小游戏.而如今,手机毫无疑问已经成为人们生活中不可或缺的部分.这是一个神奇的东西:通讯工具,外卖神器,游戏机,移 ...

  3. Android--监听ListView滚动到最底部

    监听ListView滚动到最底部使用 onScrollStateChanged(AbsListView view, int scrollState) 方法,代码大致如下: // 监听listview滚 ...

  4. Mac OSX 快捷键&命令行总览

    大家初用Mac OSX可能不习惯,特别收集总结了Mac OSX 上的快捷键,方便大家参考 ,请叫我雷锋. 一.Mac OSX 快捷键 ctrl+shift                       ...

  5. maven学习手记 - 1

    学习目标 windows下安装maven环境: 使用命令创建maven项目结构: maven项目编译测试打包安装运行: 在maven项目中使用插件.   在windows下安装maven环境 在win ...

  6. 26.68013 烧录方式 及iic生成

    硬件程序烧录 1)因为本产品要求将二进制代码和硬件PID/VID烧录在EEPROM,而不是使用CYPRESS推荐的在线下载方式,所以外部采用了8K的EEPROM.上电后68013A会将EEPROM中的 ...

  7. java无符号移位(>>>)和有符号移位(>>)

    java中>>(<<)表示有符号的移位.<<<(>>>)表示无符号移位 如: int num = 22; 二进制是0001 0110, nu ...

  8. 三、freemarker数据、模版指令

    数据类型 1.         直接指定值(字符串.数值.布尔值.集合.Map对象) 2.         字符串:直接指定字符串使用单引号.双引号,字符中间可以使用转义符“\”,如果字符内有大量特殊 ...

  9. 学习笔记--HashMap浅析

    HashMap 实现了Map 接口,其底层以一个线性数组保存哈希表,所以它既有数组查询的高效,也有哈希存取的方便. HashMap提供了默认构造器,和有参构造器,在有参构造器中,提供了两个参数,可以对 ...

  10. 【转】eclipse下使用hibernate tools实现hibernate逆向工程

    一.基本环境 Eclipse 3.6 AppFuse Struts2 2.1.0 JBoss Hibernate Tools 3.4.0 二.JBoss Hibernate Tools 3.4.0安装 ...