abbshr.github.io
abbshr.github.io copied to clipboard
Logger: 解决codecademy,wunderlist等网站被劫持
codecademy.com诡异的从正常页面跳转到空白,不知各位有没有遇到过.这是近期codecademy改版后出现的情况.
今天实在忍无可忍,因为codecademy.com/learn
仍旧跳转到该死的空白页面.
几天前我就琢磨过究竟是怎么回事,可是心烦意乱也么摸出啥头绪.今天访问wunderlist.com/job这个页面时再次发生了这个情况,它依旧一副无辜的样子,被迫跳到了该死的劫持页.我本想体验一下Ruby有多Geek,现在搞的我恨不得立马砸烂codecademy服务器.慢慢冷静下来,我开始思考,这绝不应该是codecademy的过错!不是GFW就是流量攻击者来砸场子!
我曾怀疑过iptables,Chrome.不过立马否决了:iptables的所有规则都被我清除了,Chrome的chrome://flags
标签页中恢复了默认设置,并把几乎所有被怀疑的扩展插件和应用都停用了,但情况仍旧和之前一个样.
第二步开始借助前端hack技术查找问题所在,可惜茫茫HTTP流中难以寻找线索,只在劫持页中得到这么一份html源代码:
<html><head></head><body>
<div id="sl_03_372741560" style="display:none">
<form action="http://p1.0817tt.com/fshowurl.php?id=179075" method="post" name="nnsl_03_372741560" target="_blank"><input type="submit" style="display:none" id="sbbuttonsl_03_372741560">
</form>
</div>
</body></html>
点进action
字段中的超链接,发现每次都是个随机的网站,大都类似网上商城.但暂时也没摸到头绪便想其他办法了.
然后我想看看是不是网络或浏览器遭到攻击了.换了FireFox,同样的问题再次出现.又拿手机测试了一下,令我疑惑的是手机访问竟然成功了,learn那个页面始终是正常的,并没有发生跳转.看来网络环境和浏览器的问题可以排除了.
我的手机是Nexus 5 Android 4.4.4, 上网配置了fqrouter.当我想到fqrouter时,突然想到了这是不是GFW或ISP干的好事?
为了验证我的想法,我重新整理了思路寻找一个入手点.我再次hack那个页面,这次是从learn的源页面开始.
我留意到了加载过程中的流量走向中有一个名字特别的GET请求:220.167.100.204
,于是我顺着它的remote ip直接从浏览器中进行访问,结果不出我所料,这个ip地址跳到了localhost
,当我在原始页面再入后重新启动流量监控,又发现了这个到220.167.100.204
的请求.果然这里面有猫腻.
查看了一下响应内容,竟然是个JavaScript脚本! 内容如下,省略了部分:
document.write("<img src=\"http://img.tongji.linezing.com/3500271/tongji.gif\"></img>");
var sl_url = "http://p1.0817tt.com/fshowurl.php?id=179075";
function SLP(url, pt) {
var w = window || w,
u = navigator.userAgent,
d = document;
var spp = {
rand: Math.floor(2147483648 * Math.random()),
purl: url,
popt: pt,
isop: 0,
isinit: false
};
...
...
spp.ver = {
ie: /MSIE/.test(u),
ie6: !/MSIE 7\.0/.test(u) && /MSIE 6\.0/.test(u) && !/MSIE 8\.0/.test(u) && !/MSIE 9\.0/.test(u),
ie7: !/MSIE 6\.0/.test(u) && /MSIE 7\.0/.test(u) && !/MSIE 8\.0/.test(u) && !/MSIE 9\.0/.test(u),
tt: /TencentTraveler/.test(u),
qh: /360SE/.test(u),
sg: / SE/.test(u),
cr: /Chrome/.test(u),
ff: /Firefox/.test(u),
op: /Opera/.test(u),
sf: /Safari/.test(u),
mt: /Maxthon/.test(u),
mt4: /Maxthon\/4/.test(u),
qb: /QQBrowser/.test(u),
lb: /LBBROWSER/.test(u),
gg: window.google || window.chrome,
_d1: '<object id="sl_01" width="0" height="0" classid="CLSID:6BF52A52-394A-11D3-B153-00C04F79FAA6"></object>',
_d2: '<object id="sl_02" style="position:absolute;left:1px;top:1px;width:1px;height:1px;" classid="clsid:2D360201-FFF5-11d1-8D03-00A0C959BC0A"></object>',
_d3: '<div id= sl_03_' + spp.rand + ' style="display:none"><form action="' + spp.purl + '" method="post" name="nnsl_03_' + spp.rand + '" target="_blank"><input type="submit" style="display:none" id="sbbuttonsl_03_' + spp.rand + '"/></form></div>'
};
....
....
if(getCookiewt("testibrowser")!=1){
SetCookiewt("testibrowser",1);
document.writeln("<div style=\"display:none\"><script src=\"http://s23.cnzz.com/stat.php?id=1252974124&web_id=1252974124\" anguage=\"JavaScript\"><\/script><\/div>");
document.writeln("<iframe src=\"http://js.i8001.com/browser/dzt2.html\" frameborder=\"0\" width=\"0\" height=\"0\" \/>");
}
我又对ip地址进行查询,属于四川的ip.
为了验证是他搞得鬼,于是我将脚本copy下来,在其他网页中执行一次,果不其然,同样的事情发生了,只不过这次加载html的了全部内容:
<html><head></head><body>
<img src="http://img.tongji.linezing.com/3500271/tongji.gif">
<div>
<script src="http://s23.cnzz.com/stat.php?id=1252974124&web_id=1252974124" anguage="JavaScript"></script>
<script src="http://c.cnzz.com/core.php?web_id=1252974124&t=z" charset="utf-8" type="text/javascript"></script>
<a href="http://www.cnzz.com/stat/website.php?web_id=1252974124" target="_blank" title="站长统计">站长统计</a>
</div>
<iframe src="http://js.i8001.com/browser/dzt2.html" frameborder="0" width="0" height="0"></iframe>
</body></html>
经过多次URL追踪后,得出如下关键字,包括:tongji,**站长统计 **,baidu,Ads,广告商等.
当我顺着220.167.100.204
引用来源,我找到了http://connect.facebook.net/en_US/all.js
这么个URL,我试着直接访问,果然再次跳到了localhost,而看着URL,我突然发现all.js
也包含在请求资源表里,并且好几次页面加载时都pending在这里,有时甚至failed.再次寻根溯源,找到了这个all.js
的引用之处,原来是codecademy源码中的这里:
瞬间明白这是怎么回事了.请求all.js的那个URL一定列入GFW的黑名单了,因为来自facebook.而GFW对付facebook之类的网站有的是手段,像连接重置,DNS污染,DNS劫持.而我这次碰到的应该是DNS劫持.
反过头来观察了服务器对220.167.100.204的响应,发现了X-Powered-By: PHP
,试问当今拿PHP做高并发服务器的有几家?像codecademy和facebook这样的企业会拿PHP写这种类型的网站?只能是内地吧.
来自all.js的请求其实被转移了:
应该是被劫持后请求到恶意服务器,然后响应一个301资源地址已转移,告诉浏览器一个假的地址,就是220.167.100.204
这货.
HTTP 状态码301 被请求的资源已永久移动到新位置,并且将来任何对此资源的引用都应该使用本响应返回的若干个 URI 之一。如果可能,拥有链接编辑功能的客户端应当自动把请求的地址修改为从服务器反馈回来的地址。
这就证明了为什么会在codecademy请求过程中多出个异类.
处于好奇,我又访问了包含在那两个劫持页棉中的URL,基本上都是广告,原来动不动就跳出的ad是从这来的.
http://p1.0817tt.com 为广告商跳转域名,以这个URL为基础,会生成各种随机的广告页.
http://js.i8001.com/browser/dzt2.html 就是一个随机广告页,每次打开都是一个不同的广告.
这回心理有把握了,既然是GFW作祟,fan过去不就行了.事实也证实了这一点,翻墙后再次进行流量检测,发现all.js正确加载了:
这才是all.js真正的样子:
这回也再没有220.167.100.204的跳转请求出现.劫持页面也再没出现,一切正常了.
总结一下这个问题.其实就是codecademy等外国网站,本身并没有被封,也并没做啥"坏"事,只是调用了已纳入GFW监控列表/黑名单中的URL(就像引用http://connect.facebook.net/en_US/all.js 这个脚本),导致这个URL的资源无法正确加载,而恰巧这个引用通过恶意服务器的页面里的脚本转移到广告商URL,这个URL指向的页面由脚本控制生成,首先document.write
,但是浏览器表示异步加载的脚本不允许调用该方法,因此正常的页面变成了空白页面,而wunderlist出现同样情况的原因也是调用了all.js这个脚本.归根结底,都是引用http://connect.facebook.net/en_US/all.js 惹的祸.
为了解决这个问题,你可以选择翻墙.除此之外,还可以重新本地hosts文件,将connect.facebook.net解析到127.0.0.1,并开启监听80端口的静态资源服务器,把url为/en_us/all.js的请求转发到本地的任意资源,不存在的都可以.因为这个脚本的作用不过是关联facebook社交功能:
# /etc/hosts
127.0.0.1 connect.facebook.net
在此基础上做些补充,将其他加载速度慢的脚本下载下来,比如说这个google api的plusone.js脚本也是影响页面加载速度的一大累赘:
#!/usr/bin/env node
require('http').createServer(function (req, res) {
switch (req.path){
case '/js/plusone.js':
res.end(require('fs').readFileSync('./plusone.js'));
default:
res.end('\r\n');
}
}).listen(80)
最后将服务器脚本写入启动服务:
sudo echo '/usr/local/bin/node /etc/forward.js &' >> /etc/rc.local
这样做的好处是你会发现网页的加载速度大幅提升:)