按照劫持的方法不一樣,我將劫持分爲下面兩類:html
跳轉型劫持:用戶輸入地址A,可是跳轉到地址B服務器
注入型劫持:有別於跳轉型型劫持,指經過在正常的網頁中注入廣告代碼(js、iframe等),實現頁面彈窗提醒或者底部廣告等,又分爲下面三個小類:cookie
注入js類劫持:在正常頁面注入劫持的js代碼實現的劫持網絡
iframe類劫持:將正常頁面嵌入iframe或者頁面增長iframe頁面測試
篡改頁面類劫持:正常頁面出現多餘的劫持網頁標籤,致使頁面總體大小發生變化網站
爲了獲取流量,一些電商或者相似百度這樣須要流量合做的網站都會有本身的聯盟系統,經過給予一些獎勵來獲取導流,好比:百度或者電商會有渠道分紅。ui
爲了區分哪些是第三方給予導流過來的,一般會在url地址增長相似source、from之類的參數,或者進入頁面以前經過「中間頁」種cookie。加密
這樣,當用戶輸入一個正常網址的時候,劫持方會在網絡層讓其跳轉到帶分紅或者渠道號的「中間頁」或者帶渠道號的頁面。這樣用戶進行下單或者搜索等行爲,劫持方會獲得「佣金」。url
上面說的這類case還算友好,至少用戶通常體驗不到頁面變化,還有相似跳轉到釣魚網站的case,也有不正當競爭的case:用戶輸入baidu.com跳轉到so.com或者sm.cn,而對方網站有故意作成和百度搜索差很少的樣子,那時候也幫助法務作了不少案例收集。spa
題外話:前些年,用戶使用百度搜索某些醫療類query,當即用戶就會收到電話推廣醫院,不少用戶投訴,不明真相的羣衆也指責百度,實際這類是運營商把url的關鍵詞賣給了醫療機構,百度只不過是躺槍。。。那時候還作了個項目是加密query。。。
頁面在傳輸的過程當中,被網絡層進行內容「再加工」,常見有:注入js、iframe、篡改頁面。
注入js的方式能夠經過 document.write
或者直接改html代碼片斷等方式,給頁面增長外鏈js,爲了作到更難檢測,有些運營商會捏造一個不存在的url地址,從而不被過濾或者檢測。
案例1:運營商會用本身識別的ip或者域名作js網址,wap.zjtoolbar.10086.cn這類只有在浙江移動網絡下才會被解析出來,同理ip也是
案例2:運營商很聰明,知道頁面能夠檢測全部外鏈js的域名,好比:m.baidu.com我只容許m.baidu.com/static的外鏈js,其餘js都會被記錄反饋;爲了避免被檢測出來,我碰見個case電信會訪問一個不存在的地址,好比:m.baidu.com/static/abc.js,這個地址在運營商直接返回劫持的js代碼,請求不會發到百度的服務器。
這類case比較少見,可是一些擦邊球的網站或者沒有內容的垃圾站會用這種方式,他們通常是經過熱門關鍵詞之類作SEO,打開網站實際去了廣告之類沒有任何實際內容,而頁面倒是內嵌了一個其餘網站,咱們要是識別出來不被內嵌就須要檢測。
這類case不多見,通常是在頁面底部增長js以外的div,而後展示一些非網站內容。
講了常見的劫持手段有哪些,咱們再來看看怎麼識別上面提到的這些劫持。

上圖是15年8月11日這天百度某頁面的劫持狀況,那天數據還算不錯,以前浙江移動網絡劫持率高達40%+,多數劫持來自 zjtoolbar.10086.cn
這個域名,就是移動的流量提示(還專門啓用個域名zjtoolbar,浙江toolbar)。。。
跳轉型劫持若是用單純靠Web頁面進行檢測比較困難,當時咱們作檢測是在手機百度(手百)內作檢測,因此比較簡單,用戶輸入搜索詞(query),打開百度的頁面URL,而後當頁面加載結束,APP對比訪問的URL是不是以前要訪問的URL,若是URL不一致,則記錄上報。
改寫 document.write
方法
遍歷頁面 script
標籤,給外鏈js增長白名單,不在白名單內js外鏈都上報
這個經過比較 parent
對象,若是頁面被嵌套,則 parent!==window
,要獲取咱們頁面的URL地址,可使用下面的代碼:
function getParentUrl() {
var url;
if (parent !== window) {
try {
url = parent.location.href;
} catch (e) {
url = document.referrer;
}
}
return url;
}
前面提到相似電信捏造在白名單內的js URL和篡改頁面內容的,咱們用上面提到的方法檢測不到這些信息,若是是在APP內,能夠作的事情就比較多了,除了上面以外,還能夠比較頁面的 content-length
。當時手百的作法是:
在用戶開始輸入query的時候,APP訪問一個空白頁面,頁面內只有html、title、head、body、script,而script標籤內主要代碼就是嗅探是否被劫持。
由於通常劫持不會針對某個頁面,而是針對整個網站域名,因此咱們的空白頁面也會被劫持。
一旦被劫持,那麼這麼簡單的頁面結構就很容易作頁面劫持分析,分析出來劫持手段就上報case
script內核心代碼以下:
function hiJackSniffer() {
var files = $.toArray(D.querySelectorAll('script[src]'));
var arr = [];
for (var i = 0, len = files.length; i < len; i++) {
files[i].src && arr.push(files[i].src);
}
if (arr.length) {
return sendImg(arr, 1);
}
arr = getParentUrl();
if (arr && arr.length) {
//被嵌入iframe
return sendImg([arr], 2);
}
if (D.documentElement.outerHTML.length > 4e3) {
var tmp = {};
var headjs = $.toArray(D.head.querySelectorAll('script'));
var unknownCode = [];
if (headjs.length) {
unknownCode = unknownCode.concat(headjs.map(function(v) {
return v.innerHTML;
}).filter(function(v) {
return !!v;
}));
}
var body = $.toArray(D.body.querySelectorAll('*'));
if (body.length > 1) {
unknownCode = unknownCode.concat(body.map(function(v) {
return v.outerHTML.split('\n').join('');
}).filter(function(str) {
if (/^<script id="b">/.test(str)) {
return false;
}
return true;
}));
}
return sendImg(unknownCode, 3);
}
sendImg([], 0);
}
這樣作除了能夠檢測到多餘的js外鏈,還能夠檢測出來篡改頁面內容等case。除了檢測域名劫持以外,在用戶輸入query的時刻訪問空白的頁面也能夠提早完成DNS解析,另外還能夠作劫持防護,所謂「一石三鳥」!
最簡單粗暴的就是直接上 HTTPS
,一勞永逸。再就是取證,去打官司或者警告渠道做弊者。除此以外,咱們還能夠繼續利用空白頁面作劫持檢測。
手百在沒有全量https時期(畢竟全站https牽扯的工做量不小),利用空白頁面嗅探出當前網絡環境存在劫持風險的時候,那麼就經過調用客戶端的接口,告訴客戶端本次啓動期間使用 https
,這樣既能夠下降劫持風險,又能夠經過這個頁面小流量測試https數據,未來https全量後,還能夠經過空白頁面將老版本的APP全量打開https