从TCP协议的原理来谈谈rst复位攻击
在谈RST攻击前,必须先了解TCP:如何通过三次握手建立TCP连接、四次握手如何把全双工的连接关闭掉、滑动窗体是怎么数据传输的、TCP的flag标志位里RST在哪些情况下出现。以下我会画一些尽量简化的图来表达清楚上述几点。之后再了解下RST攻击是怎么回事。
1、TCP是什么?
TCP是在IP网络层之上的传输层协议。用于提供port到port面向连接的可靠的字节流传输。
我来用土语解释下上面的几个keyword:
port到port:IP层仅仅管数据包从一个IP到还有一个IP的传输,IP层之上的TCP层加上端口后,就是面向进程了。每一个port都能够相应到用户进程。
可靠:TCP会负责维护实际上子虚乌有的连接概念,包含收包后的确认包、丢包后的重发等来保证可靠性。因为带宽和不同机器处理能力的不同,TCP要能控制流量。
字节流:TCP会把应用进程传来的字节流数据分割成很多个数据包,在网络上发送。IP包是会失去顺序或者产生反复的,TCP协议要能还原到字节流本来面目。
从上面我用PowerPoint画的TCP协议图能够看到,标志位共同拥有六个。当中RST位就在TCP异常时出现,也是我这篇文章重点关注的地方。
2、通过三次握手建立连接
以下我通过A向B建立TCP连接来说明三次握手怎么完毕的。
为了可以说清楚以下的RST攻击。须要结合上图说说:SYN标志位、序号、滑动窗体大小。
建立连接的请求中,标志位SYN都要置为1,在这样的请求中会告知MSS段大小,就是本机希望接收TCP包的最大大小。
发送的数据TCP包都有一个序号。它是这么得来的:最初发送SYN时。有一个初始序号,依据RFC的定义,各个操作系统的实现都是与系统时间相关的。之后,序号的值会不断的添加。比方原来的序号是100,假设这个TCP包的数据有10个字节。那么下次的TCP包序号会变成110。
滑动窗体用于加速传输。比方发了一个seq=100的包。理应收到这个包的确认ack=101后再继续发下一个包。但有了滑动窗体。仅仅要新包的seq与没有得到确认的最小seq之差小于滑动窗体大小。就能够继续发。
3、滑动窗体
滑动窗体毫无疑问是用来加速传输数据的。TCP要保证“可靠”,就须要对一个数据包进行ack确认表示接收端收到。有了滑动窗体,接收端就能够等收到很多包后仅仅发一个ack包。确认之前已经收到过的多个数据包。
有了滑动窗体。发送端在发送完一个数据包后不用等待它的ack。在滑动窗体大小内能够继续发送其它数据包。
举个样例来看吧。
大家看上图,标志位为.表示全部的flag都为0。标志位P表示flag为PSH的TCP包。用于高速数据传输。
前三个包是三次握手,client表示自己的滑动窗体大小是65535(我的XP机器),server端表示滑动窗体是5840(屏幕宽了,没截出来)。
从第四个包開始,client向server发送PSH包,数据长度是520字节。server发了ack确认包。
注意此时win窗体大小发生了改变哈。以此类推。
倒数第二、三包,server在滑动窗体内连续向client发包,client发送的ack 124同一时候确认了之前的两个包。
这就是滑动窗体的功能了。
假设谈到TCP攻击就须要注意,TCP的各种实现中,在滑动窗体之外的seq会被扔掉!以下会讲这个问题。
4、四次握手的正常TCP连接关闭
先画张简单的正常关闭连接状态变迁图。
FIN标志位也看到了,它用来表示正常关闭连接。图的左边是主动关闭连接方,右边是被动关闭连接方,用netstat命令能够看到标出的连接状态。
FIN是正常关闭,它会依据缓冲区的顺序来发的,就是说缓冲区FIN之前的包都发出去后再发FIN包,这与RST不同。
5、RST标志位
RST表示复位。用来异常的关闭连接,在TCP的设计中它是不可或缺的。就像上面说的一样,发送RST包关闭连接时,不必等缓冲区的包都发出去(不像上面的FIN包),直接就丢弃缓存区的包发送RST包。而接收端收到RST包后,也不必发送ACK包来确认。
TCP处理程序会在自己觉得的异常时刻发送RST包。比如,A向B发起连接,但B之上并未监听对应的port,这时B操作系统上的TCP处理程序会发RST包。
又比方,AB正常建立连接了,正在通讯时,A向B发送了FIN包要求关连接。B发送ACK后,网断了。A通过若干原因放弃了这个连接(比如进程重新启动)。
网通了后,B又開始发数据包。A收到后表示压力非常大。不知道这野连接哪来的,就发了个RST包强制把连接关了,B收到后会出现connect reset by peer错误。
6、RST攻击
A和serverB之间建立了TCP连接。此时C伪造了一个TCP包发给B,使B异常的断开了与A之间的TCP连接,就是RST攻击了。实际上从上面RST标志位的功能已经能够看出这样的攻击怎样达到效果了。
那么伪造什么样的TCP包能够达成目的呢?我们至顶向下的看。
假定C伪装成A发过去的包,这个包假设是RST包的话,毫无疑问,B将会丢弃与A的缓冲区上全部数据,强制关掉连接。
假设发过去的包是SYN包,那么,B会表示A已经发疯了(与OS的实现有关),正常连接时又来建新连接,B主动向A发个RST包。并在自己这端强制关掉连接。
这两种方式都可以达到复位攻击的效果。
似乎挺恐怖,然而关键是。怎样能伪造成A发给B的包呢?这里有两个关键因素。源port和序列号。
一个TCP连接都是四元组。由源IP、源port、目标IP、目标port唯一确定一个连接。所以。假设C要伪造A发给B的包。要在上面提到的IP头和TCP头。把源IP、源port、目标IP、目标port都填对。这里B作为server,IP和port是公开的,A是我们要下手的目标。IP当然知道,但A的源port就不清楚了,由于这可能是A随机生成的。
当然。假设可以对常见的OS如windows和linux找出生成source port规律的话,还是可以搞定的。
序列号问题是与滑动窗体相应的,伪造的TCP包里须要填序列号,假设序列号的值不在A之前向B发送时B的滑动窗体内,B是会主动丢弃的。所以我们要找到能落到当时的AB间滑动窗体的序列号。这个能够暴力解决,由于一个sequence长度是32位,取值范围0-4294967296。假设窗体大小像上图中我抓到的windows下的65535的话,仅仅须要相除,就知道最多仅仅须要发65537(4294967296/65535=65537)个包就能有一个序列号落到滑动窗体内。RST包是非常小的,IP头+TCP头也才40字节,算算我们的带宽就知道这实在仅仅须要几秒钟就能搞定。
那么。序列号不是问题。源port会麻烦点。假设各个操作系统不能全然随机的生成源port,或者黑客们能通过其它方式获取到source port,RST攻击易如反掌,后果非常严重。