http網絡劫持與DNS劫持原理及預防

現象

運營商、黑客、瀏覽器廠商、手機廠商,經過某些方式篡改了用戶正常訪問的網頁,插入廣告或者其餘一些雜七雜八的東西。在一些偏遠地區、雜牌運營商尤其常見。 html

網絡劫持的原理

  • DNS 劫持 通常而言,用戶上網的DNS服務器都是運營商分配的,因此在這個節點上,運營商能夠隨心所欲。 例如,訪問http://jiankang.qq.com/index.html,正常DNS應該返回騰訊的ip,而DNS劫持後,會返回一個運營商的中間服務器ip。訪問該服務器會一致性的返回302,讓用戶瀏覽器跳轉到預處理好的帶廣告的網頁,在該網頁中再經過iframe打開用戶原來訪問的地址。node

  • HTTP劫持 在運營商的路由器節點上,設置協議檢測,一旦發現是HTTP請求,並且是html類型請求,則攔截處理。 常見有兩種:瀏覽器

    • 相似DNS劫持返回302讓用戶瀏覽器跳轉到另外的地址。(釣魚網站就是這麼幹)
    • 在服務器返回的HTML數據中插入js或dom節點(廣告)。(比較常見)

譬以下圖: bash

被劫持怎麼辦?

  • 對於用戶來講,最最直接的就是向運營商投訴。
  • 在html 上加上 <meta http-equiv="Cache-Control" content="no-siteapp"> <meta http-equiv="Cache-Control" content="no-transform " /> 百度官方給的禁止轉碼聲明。
  • 最有用的方式,使用HTTPS ,不讓數據那麼明顯的裸奔。 https 加了SSL協議,會對數據進行加密。
  • 在開發的網頁中加入代碼過濾,大概思路就是用JavaScript代碼檢查全部的外鏈是否屬於白名單。

各類劫持的手段都有:
  1. 直接返回一個帶廣告的HTML
  2. 在原html中插入js,再經過js腳本安插廣告;
  3. iframe展現原來正常網頁。服務器

js實際對抗

  • 在window 監聽 DOMNodeInserted 事件,上報插入的dom、分析插入的dom 信息。(一般匹配全部的url,逐個比較是否白名單域名,若是不是,則斷定爲劫持,上報的同時,移除dom.parentNode.removeChild(dom)); 剛插入的dom。當心誤傷。比較穩的操做是作監測統計,再決策預防。
ul.addEventListener('DOMNodeInserted',function (e) {
        console.log(e.srcElement)
        console.log(ul.childElementCount)
    })
    ul.addEventListener('DOMNodeRemoved',function (e) {
        console.log(e.srcElement)
        console.log(ul.childElementCount)
    })

複製代碼

以下:網絡

function checkDivHijack(e) {
        var dom = e ? e.srcElement : document.documentElement;
        if (!dom.outerHTML) {
            return;     //e不是一個dom,只是插入一段文本
        }
        var imgList = (dom.nodeName.toUpperCase() == 'IMG') ? [dom] : dom.getElementsByTagName('img');
        if (!imgList || imgList.length == 0) {
            return;
        }
        var httpReg = /^http:\/\/(.*\.qq\.com|.*\.gtimg\.cn|.*\.qlogo\.cn|.*\.qpic\.cn)\//;
        var base64Reg = /^data:image/;
        var src;
        var hijack = false;
        for (var i = 0; i < imgList.length; i++) {
            src = imgList[i].src;
            if (!httpReg.test(src) && !base64Reg.test(src)) {
                hijack = true;
                break;
            }
        }
     }

複製代碼

但這樣也有漏洞,若是運營商經過div+style設置背景的方式顯示廣告圖,上述代碼就沒法檢查出來。app

  • 若是是iframe 插入的狀況,比較self 和top是否相同來處理
function checkIframeHijack() {
        var flag = 'iframe_hijack_redirected';
        if (getURLParam(flag)) {
            sendHijackReport('jiankang.hijack.iframe_ad', 'iframe hijack: ' + location.href);
        } else {
            if (self != top) {
                var url = location.href;
                var parts = url.split('#');
                if (location.search) {
                    parts[0] += '&' + flag + '=1';
                } else {
                    parts[0] += '?' + flag + '=1';
                }
                try {
                    top.location = parts.join('#');
                } catch (e) {
                }
            }
        }
    }
複製代碼

eg:dom

window.addEventListener('DOMNodeInserted', checkDivHijack);    
function checkDivHijack(e) {
        var html = e ? (e.srcElement.outerHTML || e.srcElement.wholeText) : $('html').html();
        var reg = /http:\/\/([^\/]+)\//g;
        var urlList = html.match(reg);
        if (!urlList || urlList.length == 0) {
            return;
        }
        reg = /^http:\/\/(.*\.qq\.com|.*\.gtimg\.cn|.*\.qlogo\.cn|.*\.qpic\.cn|.*\.wanggou\.com)\/$/;
        var hijack = false;
        for (var i = 0; i < urlList.length; i++) {
            if (!reg.test(urlList[i])) {
                hijack = true;
                break;
            }
        }
}

複製代碼

最終,根本解決辦法是使用HTTPS.post

如何遍歷一個dom 樹

function searchDom( node ){
    // 對node 節點處理
    if(node && node.nodeType === 1){
        console.log(node.tagName)
        if(node.tagName === 'IMG'){
            // ...  作白名單判斷
        }
    }
    var i = 0, childNodes = node.childNodes, item; 
    for(; i < childNodes.length; i++){
        item = childNodes[i];
        if(item.nodeType === 1){
            // 遞歸遍歷子節點
            searchDom(item)
        }
    }
}

複製代碼

參考連接
參考連接
https劫持網站

3-5年內部崗位(平安、樂信、500萬、vivo、oppo)推薦機會,歡迎發簡歷到: zgxie@126.com

相關文章
相關標籤/搜索