從++[[]][+[]]+[+[]]='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

相關文章
相關標籤/搜索