【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,就会引起错误了。

见招拆招,这个比较好办,我们只需要把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%。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏互联网杂技

Angular 1 vs. Angular 2 深度比较

AngularJS 2 尽管还在Alpha阶段,但主要功能和文档已经发布。让我我们了解下Angular 1 和 2 的区别,以及新的设计目标将如何实现。 Ang...

32910
来自专栏向治洪

android开发性能分析

1 背景 其实有点不想写这篇文章的,但是又想写,有些矛盾。不想写的原因是随便上网一搜一堆关于性能的建议,感觉大家你一总结、我一总结的都说到了很多优化注意事项...

2095
来自专栏大史住在大前端

javascript基础修炼(5)—Event Loop

如果没有详细钻研过异步队列,答对的可能性很低。题目的考察点很明确,就是javascript中最核心的特点之一的【异步】,了解了原理以后,你就会明白javascr...

732
来自专栏有趣的Python

16- vue django restful framework 打造生鲜超市 -购物车功能实现

Django2.0.2(Django-rest-framework)以及前端vue开发的前后端分离的商城网站 线上演示地址: http://vueshop.mt...

51711
来自专栏前端小吉米

如何写出一手好的小程序之多端架构篇

为了大家能更好的开发出一些高质量、高性能的小程序,这里带大家理解一下小程序在不同端上架构体系的区分,更好的让大家理解小程序一些特有的代码写作方式。

973
来自专栏闻道于事

使用ichartjs生成图表

官网:http://www.ichartjs.com/   ichartjs 是一款基于HTML5的图形库。使用纯javascript语言, 利用HTML5的c...

4557
来自专栏iOS技术

iOS 多个scrollview联动(附DEMO)

在移动应用实际开发过程中,往往会有多个scrollview嵌套的界面需求,这种需求已经司空见惯,解决方案也多种多样,这里就介绍一下我认为最优的解决方案。

3077
来自专栏技术博文

关于微信二次分享,标题变链接的解决方法(二)----代码部分

声明: 本篇博文只是个人工作中的分享总结,仅代表个人观点,虽然解决了不少网友的问题,但同时也引来了一些网友的不满,所以特此声明,当您遇到本博文解决不了的问题,可...

3296
来自专栏编程微刊

2018年各大互联网前端面试题四(美团)

1232
来自专栏Java3y

纳税服务系统总结

纳税服务系统总结 纳税服务系统是我第一个做得比较大的项目(不同于javaWeb小项目),该项目系统来源于传智Java32期,十天的视频课程(想要视频的同学关注我...

2719

扫码关注云+社区