为了确保端到端的可靠传输,TCP对所发送出的每个数据包都分配序列编号,当对方收到数据包后则向发送方进行确认,接收方利用序列号来确认数据包的先后顺序,并丢弃重复的数据包。TCP序列号在TCP数据包中占32位字节,有发送序列号SEQS和确认序列号SEQA两种,它们分别对应SYN和ACK两个标志。当SYN置1时,表示所发送的数据包的序列号为SEQS ;当ACK置1时,表示接收方准备接收的数据包的序列号为SEQA 。
① Xser → Server:SYN(SEQS=ISNC);使用User的IP作为源地址
② Server → User :SYN(SEQS=ISNS),ACK(SEQA=ISNC+1)
③ Xser → Server:ACK(SEQA=ISNS+1);使用User的IP作为源地址
在这里,Xser以User的身份向服务器发送初始序列号,并置SYN=1,请求与服务器建立连接;当服务器收到该请求后,向User返回应答序列号,如果此时User能正常工作,则认为这是一个非法数据包而终止连接,使攻击者的目的落空,否则,攻击者将继续以User的身份向服务器发送已推测出的确认序列号ISNS+1,并与服务器建立连接,进而可在服务器上行使User的权限,执行相应的操作。
使用这种攻击需要具备两个基本条件:一是能推测出序列号ISNS的值;二是所冒充的可信任主机不能正常工作。其中,最关键的是要推测出由服务器返回的序列号ISNS的值。由服务器返回的这个值可能是个随机数,它通常与被信任主机和服务器间的RTT时间有关,必须经过多次采样和统计分析,才可能推测到这个值。通常,可重复多次与被攻击主机的某个端口(如SMTP)建立正常连接,然后断开,并记录每次连接所设定的ISN值。另外,还需要多次测试可信任主机与服务器间的RTT时间
TCP协议工作在OSI的传输层,是一种可靠的面向连接的数据流协议,TCP之所以可靠,是因为它保证了传送数据包的顺序。顺序是用一个序列号来保证的。响应包内也包括一个序列号,表示接收方准备好这个序列号的包。在TCP传送一个数据包时,它会把这个数据包放入重发队列中,同时启动计时器,如果收到了关于这个包的确认信息,便将此数据包从队列中删除,如果在计时器超时的时候仍然没有收到确认信息,则需要重新发送该数据包。另外,TCP通过数据分段中的序列号来保证所有传输的数据可以按照正常的顺序进行重组,从而保障数据传输的完整。
在TCP通讯中主要有连接的建立、数据的传输、连接的关闭三个过程!每个过程完成不同的工作,而且序列号和确认号在每个过程中的变化都是不同的。
2.1 TCP建立连接
TCP建立连接,也就是我们常说的三次握手,它需要三步完成。在TCP的三次握手中,发送第一个SYN的一端执行的是主动打开。而接收这个SYN并发回下一个SYN的另一端执行的是被动打开。
这里以客户端向服务器发起连接来说明。
1) 第1步:客户端向服务器发送一个同步数据包请求建立连接,该数据包中,初始序列号(ISN)是客户端随机产生的一个值,确认号是0;
2) 第2步:服务器收到这个同步请求数据包后,会对客户端进行一个同步确认。这个数据包中,序列号(ISN)是服务器随机产生的一个值,确认号是客户端的初始序列号+1;
3) 第3步:客户端收到这个同步确认数据包后,再对服务器进行一个确认。该数据包中,序列号是上一个同步请求数据包中的确认号值,确认号是服务器的初始序列号+1。
注意:因为一个SYN将占用一个序号,所以要加1。
初始序列号(ISN)随时间而变化的,而且不同的操作系统也会有不同的实现方式,所以每个连接的初始序列号是不同的。TCP连接两端会在建立连接时,交互一些信息,如窗口大小、MSS等,以便为接着的数据传输做准备。
RFC793指出ISN可以看作是一个32bit的计数器,每4ms加1,这样选择序号的目的在于防止在网络中被延迟的分组在以后被重复传输,而导致某个连接的一端对它作错误的判断。
2.2 TCP传输数据
在TCP建立连接后,就可以开始传输数据了。TCP工作在全双工模式,它可以同时进行双向数据传输。这里为了简化,我们只谈服务器向客户端发送数据的情况,而客户端向服务器发送数据的原理和它是类似的,这里便不重复说明。
服务器向客户端发送一个数据包后,客户端收到这个数据包后,会向服务器发送一个确认数据包。
传输数据的简要过程如下:
1) 发送数据:服务器向客户端发送一个带有数据的数据包,该数据包中的序列号和确认号与建立连接第三步的数据包中的序列号和确认号相同;
2) 确认收到:客户端收到该数据包,向服务器发送一个确认数据包,该数据包中,序列号是为上一个数据包中的确认号值,而确认号为服务器发送的上一个数据包中的序列号+所该数据包中所带数据的大小。
数据分段中的序列号可以保证所有传输的数据按照正常的次序进行重组,而且通过确认保证数据传输的完整性。
2.3 TCP关闭连接
前面我们提到,建立一个连接需要3个步骤,但是关闭一个连接需要经过4个步骤。因为TCP连接是全双工的工作模式,所以每个方向上需要单独关闭。在TCP关闭连接时,首先关闭的一方(即发送第一个终止数据包的)将执行主动关闭,而另一方(收到这个终止数据包的)再执行被动关闭。
关闭连接的4个步骤如下:
1) 第1步:服务器完成它的数据发送任务后,会主动向客户端发送一个终止数据包,以关闭在这个方向上的TCP连接。该数据包中,序列号为客户端发送的上一个数据包中的确认号值,而确认号为服务器发送的上一个数据包中的序列号+该数据包所带的数据的大小;
2) 第2步:客户端收到服务器发送的终止数据包后,将对服务器发送确认信息,以关闭该方向上的TCP连接。这时的数据包中,序列号为第1步中的确认号值,而确认号为第1步的数据包中的序列号+1;
3) 第3步:同理,客户端完成它的数据发送任务后,就也会向服务器发送一个终止数据包,以关闭在这个方向上的TCP连接,该数据包中,序列号为服务器发送的上一个数据包中的确认号值,而确认号为客户端发送的上一个数据包中的序列号+该数据包所带数据的大小;
4) 第4步:服务器收到客户端发送的终止数据包后,将对客户端发送确认信息,以关闭该方向上的TCP连接。这时在数据包中,序列号为第3步中的确认号值,而确认号为第3步数据包中的序列号+1;
注意:因为FIN和SYN一样,也要占一个序号。理论上服务器在TCP连接关闭时发送的终止数据包中,只有终止位是置1,然后客户端进行确认。但是在实际的TCP实现中,在终止数据包中,确认位和终止位是同时置为1的,确认位置为1表示对最后一次传输的数据进行确认,终止位置为1表示关闭该方向的TCP连接。
1、找出一台能对S进行rlogin登录的远程主机R。
2、让R无法响应。
3、使用M伪造R的IP身份,向S进行TCP第一次握手。
4、使用主机T,发送系列SYN请求给S,分析S的ISN算法。预测一个S会响应步骤3的第二次握手的ISN。
5、根据步骤4的预测ISN值,向S进行TCP第三次握手。完成攻击。
1、使R无法响应
WHY:因为后边要使用R的IP来给S发送伪造请求(第一次握手),之后,还要给S发送伪造身份的第三次握手,而不能让真正的R进行握手。所以不能让R响应。
tag:在这个地方,我遇到了问题,先按住不表。其实上边这个WHY只是我个人理解,我看的一本书上是这样讲的:如果远程服务器发现有人尝试使用服务器IP地址进行假连接,它将发送TCP重置数据包关闭连接。。之后我理解了会再回来的。
DO:要让R不能响应,我们直接给它个 SYN Flood,让它闭嘴。
2、预测TCP序列号
WHY:让R不能响应之后,下一步我们要做的就是:在M上用R的IP身份向S发送一个TCP连接请求(第一次握手),这时候S会正常响应(第二次握手),但是它不会收到正常的第三次响应,因为真正的R被我们封口了。接着,我们直接从M上制造一个第三次握手响应S。。。这个过程总结起来其实就是:我们在M上跳过第二次握手,直接给了S一个第一次握手和第三次握手,建立起M<==>S的TCP连接,完成攻击。
而这其中的难点在于:由于每个TCP报文都会带一个TCP序列号,我们知道,当对一个SYN报文进行ACK的时候被要求将当前的TCP序列号加1。这样的计算量就是小学生都可以解决。问题是,我们现在是在讨论“初始”时候的TCP序列号。即Client发起TCP连接请求SYN的时候,会发送一个自己的初始序号ISN,而Server在响应这个SYN时,不仅要将这个ISN加1进行ACK,还要发送Server自己的ISN,这个跟Client那个ISN是没有关系的。两边的ISN都是双方根据自己的选择算法选择出来的。。。
而这个选择算法存在漏洞(tag:现在大部分的操作系统已经对此改进,将其随机化了)!
比如,RFC 793 [Postel 1981c]中说明是:ISN可看作是一个32比特的计数器,每4秒加1。。。仅仅用每4秒加1这么简单的算法来生成,那么我们只要自己从其它主机手动给S连接请求,然后分析从S返回的响应中的ISN,就可以完美地确定到我们上边那一次第三次握手时要给它的ISN+1是几了(其实也不完美,毕竟网络流量比较复杂,难保S会有其它连接使得ISN数据后移了。所以标题说“预测”。just try it)。
DO:(我们已经假定了S上存在“ISN漏洞”,但是具体情况并不一定是上边说的“每4秒加1”)使用测试主机T,对S发出一系统SYN请求,通过分析其响应中的属于Server方(被动连接方)的ISN,最终给出一个预测的TCP序列号值,准备用于上边那个第三次握手。