从++[[]][+[]]+[+[]]='10'谈安全

一开始我也有疑问,为何 ++[[]][+[]]+[+[]]='10' javascript

不得不信,因而咱们要慢慢的分析:java

分析基础符号

[]分析

[]有两个做用:git

1. 数组github

2. 访问属性和方法web

例子:ajax

[1,2,3,4]   // 数组
"abc"[0]     // 属性
[1,2]["length"]  // 方法

+运算符的做用

1. 建立数字
2. 将两个值相加
3. 链接字符串
4. 建立字符串后端

两个数相加

operand + operand = result数组

1. 若是操做符数中有一个对象,它将转换为原始值(stringnumberboolean)浏览器

2. 若是操做符数中有一个字符串,第二个操做数将转换成字符串,而且链接在一块儿转换成一个字符串安全

3. 在其它状况之下,两个操做数转换为数字而且将执行加法运算

其中,对象转换的规则:

1. 若是对象类型是一个Date,可使用toString()方法

2. 在其它状况下使用valueOf()方法,它将返回一个原始值

3. 若是valueOf()方法不能将它返回一个原始值,可使用toString()方法。而这种状况大部分状况下都会发生

例子:

// 数字和字符串
var result = 1 + "5";             // "15"
// 数字和数组
var result = [1,3,5] + 1;         // "1,3,51"
// 数字和布尔值
var result = 10 + true;         // 11
// 数字和对象
var result = 15 + {};            // "15[object Object]"
// 数字和null
var result = 8 + null;             // 8
// 字符串和null
var result = "queen" + null;    // "queennull"
//  数字和undefined
var result = 12 + undefined;     // NaN

下面这张图是两个变量相加的类型结果:

           

位于操做数以前(+x)

一元正号运算符(unary plus operator)位于其操做数前面,计算其操做数的数值,若是操做数不是一个数值,会尝试将其转换成一个数值。它能够将字符串转换成整数和浮点数形式,也能够转换非字符串值 truefalse  null。小数和十六进制格式字符串也能够转换成数值。负数形式字符串也能够转换成数值(对于十六进制不适用)。若是它不能解析一个值,则计算结果为 NaN。

例子:

+3     // 3
+"3"   // 3
+true  // 1
+false // 0
+null  // 0
+[]    // 0

递增(++)

递增运算符(increment operator)为其操做数增长1,返回一个数值。

 

解析++[[]][+[]]+[+[]]

首先把这个表达式拆分开来,如:

++[[]][+[]]
+
[+[]]

由上面的基础分析可知, +[] === 0  是彻底正确的,故咱们能够简化以下:

 

++[[]][0]
+
[0]

 

[[]][0] 返回内部数组 ([])。可是因为语言规范, [[]][0] === [] 是不正确的,所以咱们暂时用A来代替里面的数组。

++[[]][0] == A + 1, 由于 ++ 的意思是”+1”。
++[[]][0] === +(A + 1);这是一个数值,由于递增(++)返回的永远都是一个数值

所以,表达式能够简化以下:

+([] + 1)
+
[0]

由上面的基础符号分析能够简化表达式以下:

1   // 参考+在操做数前面
+
"0"  // 参考两个变量相加的对象转换规则

故最终结果为'10'。

用途

上面只是一个简单的例子,其实用这些字符串是能够写出真正有用的代码的,例如:

(![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]+(![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[!+[]+!+[]+[+[]]]+[+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[!+[]+!+[]+[+[]]]    // alert(1)

能够在今生成想要的代码:http://www.jsfuck.com/

看着一些字符串能够执行,想必你们都有疑虑,用在哪些地方呢?

因为这样的代码属于混淆代码,不容易被识别,咱们能够用在帐户的安全校验上,好比,能够在Web端帐户登录以前从后端拿到一段这样的可执行代码,将执行结果写入cookie、token或者ajax请求里,这样能够防止一部分黑产用工具刷接口来获取数据。

因为黑产如今采用的工具都是易语言写的。基于winhttp.dll和winInet.dll的,不具有js引擎,因此若是web端在提交登录以前获取并执行后端的一段这样的代码,一来能够以混淆的代码使得黑产不容易看懂,二来若是黑产想破解的话,就须要一个js引擎或者无头浏览器,其成本是很高的。

用于安全上只是其中的一个例子,聪明的你可能还有更好的使用场景,不妨分享出来。

参考资料

Addition (+):https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators

jsFuck: https://github.com/aemkei/jsfuck

JavaScript addition operator in details: https://rainsoft.io/javascriptss-addition-operator-demystified/

Why does ++[[]][+[]]+[+[]] return the string “10”?:https://stackoverflow.com/questions/7202157/why-does-return-the-string-10

相关文章
相关标签/搜索