一開始我也有疑問,爲何 ++[[]][+[]]+[+[]]='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. 若是操做符數中有一個對象,它將轉換爲原始值(string
、number
或boolean
)瀏覽器
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
下面這張圖是兩個變量相加的類型結果:
一元正號運算符(unary plus operator)位於其操做數前面,計算其操做數的數值,若是操做數不是一個數值,會嘗試將其轉換成一個數值。它能夠將字符串轉換成整數和浮點數形式,也能夠轉換非字符串值 true
,false
和
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