TTL 由8比特组成,可以用来确定在到达目的地之前数据包经过了几跳,当计算机发送一个IP数据包时会设置TTL字段为数据包在到达目的地之前所应经过的中继跳转的上限值,数据包每经过一个路由设备,TTL值就自减一,若减至0还未到目的地,路由器会丢弃该数据包以防止无限路由循环。
Nmap进行伪装扫描时,伪造数据包的TTL值是没有经过计算的,因而可以利用TTL值来分析所有来自Nmap扫描的数据包,对于每个被记录为Nmap扫描的源地址,发送一个ICMP数据包来确定源地址与目标机器之间隔了几跳,从而来辨别真正的扫描源。
Nmap的-D参数实现伪造源地址扫描nmap 192.168.220.128 -D 8.8.8.8
使用Scapy库来获取源地址IP及其TTL值,代码如下。
from scapy.all import * from IPy import IP as PYIP
def Get_TTL(pkt): try: if pkt.haslayer(IP): ip_src = pkt.getlayer(IP).src ip_sport = pkt.getlayer(IP).sport ip_dst = pkt.getlayer(IP).dst ip_dport = pkt.getlayer(IP).dport ip_ttl = str(pkt.ttl) print("[+] 源地址: %15s:%-5s --> 目标地址: %15s:%-5s --> TTL: %-5s"%(ip_src,ip_sport,ip_dst,ip_dport,ip_ttl)) except Exception: pass
if __name__=="__main__": sniff(prn=Get_TTL,store=0)
|
运行脚本监听,启动Nmap伪造源地址扫描即可看到结果:
接着添加checkTTL()
函数,主要实现对比TTL值进行源地址真伪判断:
from scapy.all import * import time import optparse from IPy import IP as IPTEST
ttlValues = {} THRESH = 5
def testTTL(pkt): try: if pkt.haslayer(IP): ipsrc = pkt.getlayer(IP).src ttl = str(pkt.ttl) checkTTL(ipsrc, ttl) except: pass
def checkTTL(ipsrc, ttl): if IPTEST(ipsrc).iptype() == 'PRIVATE': return
if not ttlValues.has_key(ipsrc): pkt = sr1(IP(dst=ipsrc) / ICMP(), retry=0, timeout=1, verbose=0) ttlValues[ipsrc] = pkt.ttl
if abs(int(ttl) - int(ttlValues[ipsrc])) > THRESH: print('\n[!] Detected Possible Spoofed Packet From: ' + ipsrc) print('[!] TTL: ' + ttl + ', Actual TTL: ' + str(ttlValues[ipsrc]))
if __name__ == '__main__': parser = optparse.OptionParser("[*]Usage python spoofDetect.py -i <interface> -t <thresh>") parser.add_option('-i', dest='iface', type='string', help='specify network interface') parser.add_option('-t', dest='thresh', type='int', help='specify threshold count ') (options, args) = parser.parse_args() if options.iface == None: conf.iface = 'eth0' else: conf.iface = options.iface if options.thresh != None: THRESH = options.thresh else: THRESH = 5 sniff(prn=testTTL, store=0)
|