從++[[]][+[]]+[+[]]='10'談安全


一開始我也有疑問,為什么 ++[[]][+[]]+[+[]]='10' 

不得不信,於是我們要慢慢的分析:

分析基礎符號

[]分析

[]有兩個作用:

1. 數組

2. 訪問屬性和方法

例子:

[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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM