0x00 前言


最近在处理了一些HTTP劫持的案例和拜读业内不少大牛的文章之后,觉得有必要把最近的一些关于劫持案例的分析和思考记录下来,以留作日后备忘。

首先是一例典型的旁路劫持案例:

劫持者应该是利用在运营商内部的便利条件,在网关路由器上添加嗅探程序,嗅探明文HTTP请求数据包,拿到要劫持的数据包之后,马上给请求者返回HTTP response(302 到其他 url),并且立即关闭当前HTTP 请求。劫持者 302 的 url 是原网站的一个计费请求,类似淘宝推广链接,但是比较让人郁闷的是,劫持者返回的数据包是两个 TCP 数据包,偶尔会出现 TCP 报乱序(劫持技术不过关),导致客户端无法识别,从而导致页面白屏,严重影响用户体验 !

0x01 分析


下面介绍一下我是如何从数据包分析和定位劫持路由的:

case 背景:山西移动部分地区,访问国内顶级中文导航网站出现白屏现象。

页面请求后得到奇怪数据返回:

请求中 Connection 字段为 keep alive 且请求协议是 1.0 而返回的header 关闭了请求,返回一段奇怪的js,跳转到另外一个 url

接下来观察 TCP flow:

这次TCP 连接上有 3 个奇怪的现象,都可以证明这是一次处于链路中的劫持,之后如果遇到类似的情况也可以从这三个方面入手来处理:

  1. server 给 client 的 TCP 报的 TTL 不一致,且抖动很大。

  2. server 给 client 的 IP identification,出现不符合 RFC 标准的情况

0x02 TTL 不一致的情况:


客户端接受的数据包TTL是 51 ,后面来自真实 server 的TTL 是 47,还有 1022 和 1024(本来应该在前面) 都是两个来自 劫持者的数据包,但是 fin 包在前,提前关闭连接,导致HTTP应用层拿不到正确的数据,导致浏览器白屏。

这次 TCP 连接上的其他数据包,可以看到有 部分 数据包,被抛弃,而且被抛弃的数据包的 TTL 和 握手包的TTL 相等(一般 握手包 不会被劫持,说明被抛弃的包是来自 真实的服务器的)是 47 。

0x03 IP identification 异常现象:


RFC定义:

所以对于给定地址和协议的 ip 包来说,它的identification应该是公差为 1 的单调递增数列:

但是在这次连接中,劫持者的 identification 等于被劫持的 identification:

劫持者:

被劫持者:

仔细看,可以发现 993 和 1022 这两个包的identification 是一样的,多次抓包也是这样,所以这里可以判断,链路上肯定出了问题。

从这以上两个特征,基本上可以得出结论:

劫持者提前给浏览器返回了响应,且关闭了 HTTP 连接。导致正确的 数据包没有被接受,使得浏览器发生了异常跳转。而用户页面出现白屏的情况是劫持失败,劫持者的数据包乱序(程序错误),导致应用层无法获得争取 HTTP 响应。

劫持过程应该类似于:

结论已经获得,但是问题的解决就是要定位到相应的劫持路由,然后向有关部门反馈:

定位的方法我推荐几种:

  1.  如果出现一定数量的用户反馈,可以多联系几位用户(不同网路环境下,能复现劫持),抓包,然后获取 trace 截图,如果他们出现某几跳路由的重复,就可以缩小定位范围,或者直接定位路由IP。

  2. 根据劫持包的TTL反推,用 scapy 来构造自定义的,可以复现劫持的HTTP请求包,然后以 TTL 从 1 开始递增发包,出现劫持响应时,可以判断劫持者的位置。

0x04 参考文章:


谢谢这两篇文章的作者,指定迷津