【HTTP劫持和DNS劫持】實際JS對抗


1、對於DIV注入的,可以初始化時檢查全部html代碼。

檢測是否被劫持比較簡單,但對抗就略麻煩,這個在說完第2點之后再解釋。

 

2、對於js注入,可以在window監聽DOMNodeInserted事件。

事件有srcElement,可以獲取到剛插入的dom節點。
這里開始簡單粗暴的做正則匹配,匹配所有url。
再逐個比較是否白名單域名,如果不是,則判定為劫持。可以上報,同時可以移除dom.parentNode.removeChild(dom);
但這樣容易造成誤傷,因為正常頁面中可能有外部鏈接,或者一些純文本url。

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

后來改為

    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設置背景的方式顯示廣告圖,上述代碼就無法檢查出來。

那么,就還需要檢查style的情況,但style情況就更復雜了。可能是<style>,也可能是inline樣式,最終還是要回到url識別上。
那么做個折衷,我們繼續用最初的純文本正則匹配url的方式,但跳過純文本的情況(例如修改div的內容,替換為一段文本),只檢查插入dom的情況。
具體方法是

        if (!dom.outerHTML) {
            return;     //e不是一個dom,只是插入一段文本
        }

回到剛才第一點的問題,監測第一點的情況,可以用一樣的做法。但是,對抗就麻煩很多,因為廣告dom節點可以插在body第一層,也可以插在某個內容div中。如果簡單粗暴的把廣告dom節點到body的全部div都移除,可能會造成大面積的誤傷。
所以,針對這個情況,我們還在做進一步的監測統計。

 

3、對於iframe的情況,要檢測非常簡單,只需要比較self和top是否相同。

不過,要完整解決這個嵌套劫持,就要知道運營商的小把戲。
試想一下,iframe前,請求http://www.host.com/xxx.html ,就被劫持,302重定向到一個iframe的頁面,這個頁面使用iframe重新加載我們原來要請求的html。
那么,此時在iframe中的html為什么能夠順利加載回來呢?而不是又被劫持?
我們猜想,運營商應該在url中加了一個參數,標記是否已經劫持過。
而實際監測發現,我們的猜想也是正確的。

呃,我們仔細看,還可以發現運營商做這個劫持也非常粗暴,如果頁面依賴hash,就會引起錯誤了。
Image

見招拆招,這個比較好辦,我們只需要把top的地址修改為self地址即可。一來沖掉iframe,二來繞過劫持。

    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) {
                }
            }
        }
    }

為了安全起見,防止運營商有新招數,所以這里只嘗試一次,用iframe_hijack_redirected參數標記,已經嘗試過。

按照統計情況來看,運營商還是挺猖狂的,平均大約有6~10個劫持上報,大概占整個QQ健康用戶的3%到5%。


免責聲明!

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



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