无意中发现大量恶意url下载回来的是同一个md5,分析后发现国内存在恶意url劫持现象,遂对劫持点做了下探测。

探测原理

通过TTL衰减来做测量。TTL是IP协议包中的一个值,它告诉网络,数据包在网络中的时间是否太长而应被丢弃。有很多原因使包在一定时间内不能被传递到目的地。解决方法就是在一段时间后丢弃这个包,然后给发送者一个报文,由发送者决定是否要重发。基于这个特性,我们可以设置http请求里面的TTL值来观察看是在第几跳发生的劫持,然后通过traceroute来获得劫持点的IP,这样我们就可以知道在什么位置发生的劫持了。

举个例子

比如下面这个url,通过脚本测试,发现在第8跳存在劫持。

$ python hijack_chain_trace.py 8 http://43.x.x.x/AB4g5/Josho.arm

然后通过traceroute查看第8跳路由器IP是什么:

Snip20180517_7
从上图可以看出第8跳IP是59.43.28.65,这样我们就可以知道在这个点发生的劫持了。

探测脚本

#!/usr/bin/env python
# -*- coding: UTF-8 -*-

#Author: https://twitter.com/kenshin_acs
#hijack_chain_trace.py 

import sys
import random
from scapy.all import *
from urlparse import urlparse


def request(host, port, url, ttl):
    getStr = 'GET %s HTTP/1.1\r\nHost: %s\r\n\r\n' %(url, host)
    print getStr
    req = IP(dst=host, ttl = ttl) / TCP(dport=port, sport=random.randint(1025,65500), seq=65231, ack=1, flags='P''A') / getStr
    req.show()
    reply = sr(req, multi = 1, timeout =1)
    print "\r\n===========reply=========="
    for r in reply:
        r.hexraw()

if __name__ == "__main__":
    ttl = int(sys.argv[1])
    o = urlparse(sys.argv[2])
    port = o.port
    if not port and  o.scheme == 'http':
        port = 80
    elif not port and o.scheme == 'https':
        port = 443
    port = int(port)

    request(o.hostname, port, o.path, ttl)