详解TCP/IP协议栈面临的五大网络安全问题
原文https://cloud.tencent.com/developer/news/53986
1. IP欺骗
IP Spoof即IP 电子欺骗,可以理解为一台主机设备冒充另外一台主机的IP地址与其他设备通信,从而达到某种目的技术。早在1985年,贝尔实验室的一名工程师Robbert Morris在他的一篇文章“A weakness in the 4.2bsd UNIX TCP/IP software”中提出了IP Spoof的概念,有兴趣的读者可参见原文:http://www.coast.net/~emv/tubed/archives/Morris_weakness_in_ TCPIP.txt 。
但要注意:单纯凭借IP Spoof技术不可能很好地完成一次完整的攻击,因为现有IP Spoof技术是属于一种“盲人”式的入侵手段。
一般来说,IP欺骗攻击有6个步骤:
(1)首先使被信任主机的网络暂时瘫痪,以免对攻击造成干扰;
(2)然后连接到目标机的某个端口来猜测ISN基值和增加规律;
(3)接下来把源地址伪装成被信任主机,发送带有SYN标志的数据段请求连接;
(4)然后等待目标机发送SYN+ACK包给已经瘫痪的主机;
(5)最后再次伪装成被信任主机向目标机发送的ACK,此时发送的数据段带有预测的目标机的ISN+1;
(6)连接建立,发送命令请求。
下面是它的两个关键步骤:
(1)使被信任主机失去工作能力
为了伪装成被信任主机而不露馅,需要使其完全失去工作能力。由于攻击者将要代替真正的被信任主机,他必须确保真正的被信任主机不能收到任何有效的网络数据,否则将会被揭穿。有许多方法可以达到这个目的(如SYN洪水攻击、Land等攻击)。
(2)序列号取样和猜测
对目标主机进行攻击,必须知道目标主机的数据包序列号。通常如何进行预测呢?往往先与被攻击主机的一个端口(如25端口)建立起正常连接。通常,这个过程被重复N次,并将目标主机最后所发送的ISN存储起来。然后还需要估计他的主机与被信任主机之间的往返时间,这个时间是通过多次统计平均计算出来的。如果往返连接增加64,000,则现就可以估计出ISN的大小是128,000乘以往返时间的一半,如果此时目标主机刚刚建立过一个连接,那么再加上64,00。一旦估计出ISN的大小,就开始着手进行攻击,当然你的虚假TCP数据包进入目标主机时,如果刚才估计的序列号是准确的,进入的数据将被放置在目标机的缓冲区中。
但是在实际攻击过程中往往没这么幸运,如果估计的序列号小于正确值,那么将被放弃。而如果估计的序列号大于正确值,并且在缓冲区的大小之内,那么该数据被认为是一个未来的数据,TCP模块将等待其他缺少的数据。如果估计序列号大于期待的数字且不在缓冲区之内,TCP将会放弃它并返回一个期望获得的数据序列号。伪装成被信任的主机IP后,此时该主机仍然处在瘫痪状态,然后向目标主机的被攻击端口(如25)发送连接请求。目标主机立刻对连接请求作出反应,发更新SYN+ACK确认包给被信任主机,因为此时被信任主机仍然处于瘫痪状态,它当然无法收到这个包,紧接着攻击者向目标主机发送ACK数据包,该数据包使用前面估计的序列号加1。如果攻击者估计正确的话,目标主机将会接收该ACK。连接就正式建立起了,可以开始数据传输了。
对于来自网络外部的欺骗,防范的方法很简单,只需要在局域网的对外路由器上加一个限制设置就可以实现了,在路由器的设置里面禁止运行声称来自于网络内部的信息包。
对于来自局域网外部的IP欺骗攻击的防范则可以使用防火墙进行防范,但是对于来自内部的攻击通过设置防火墙则起不到什么作用,这个时候应该注意内部网的路由器是否支持内部接口。如果路由器支持内部网络子网的两个接口,则必须提高警惕,因为它很容易受到IP欺骗。
通过对信息包的监控来检查IP欺骗攻击将是非常有效的方法,使用netlog等信息包检查工具对信息的源地址和目的地址进行验证,如果发现了信息包来自两个以上的不同地址,则说明系统有可能受到了IP欺骗攻击,防火墙外面正有黑客试图入侵系统。
2. SYN Flooding
SYN Flooding是最为有效和流行的一种DoS攻击形式。它利用TCP三次握手协议的缺陷,向目标主机发送大量的伪造源地址的SYN连接请求,消耗目标主机的资源,从而不能够为正常用户提供服务。
在TCP会话初期,有所谓的“三次握手”过程:对每次发送的数据量是怎样跟踪进行协商使数据段的发送和接收同步,根据所接收到的数据量而确定的数据确认数及数据发送、接收完毕后何时撤消联系,并建立虚连接。为了提供可靠的传送,TCP在发送新的数据之前,以特定的顺序将数据包进行编号,并需要等待这些包传送给目标机之后的确认消息。TCP总是用来发送大批量的数据。当应用程序在收到数据后要做出确认时也要用到TCP。由于TCP要时刻跟踪,这需要额外开销,使得TCP的格式有些显得复杂。
TCP三次握手的步骤如下:
(1)设主机A要与主机B通信,要建立一个TCP连接。首先,主机B(在这儿是服务器),必须先运行一个服务器进程,发出一个“被动找开”命令给TCP。之后服务器进程便不断探测端口,看是否有客户进程有连接请求。并处于“听”状态。客户端主机A的应用进程,向其TCP发“主动打开”命令,指明要与某个IP地址的某个端口建立TCP连接。第一次主机A的TCP便向主机B的TCP发出连接请求报文。TCP报文中指明了要连接的IP地址(隐含TP数据报指明)和端口号,设置能够接受的TCP数据段最大值,以及一些用户数据,SYN=1,ACK=0。这称为“第一次握手”。
(2)主机A的连接请求到达主机B后,主机B的TCP查看是否有进程在侦听该端口,如没有,就发送一个RST=1的应答,拒绝连接,否则将到达TCP数据段留给“侦听”进程。“侦听”进程将发回一个应答TCP报文段,其中SYN=1,ACK=1,确认序号ACKSEQ=X+1,同时自己选一个发送序号SEQ=Y。这是“第二次握手”。
(3)主机A收到主机B的确认报文后,再向主机B发出一个确认TCP报文段,其中SYN=1,ACK=1,SEQ=X+1,ACKSEQ=Y+1,这就完成了“第三次握手”。
在SYN Flooding攻击中,黑客机器向受害主机发送大量伪造源地址的TCP SYN报文,受害主机分配必要的资源,然后向源地址返回SYN+ACK包,并等待源端返回ACK包,如图1所示。由于源地址是伪造的,所以源端永远都不会返回ACK报文,受害主机继续发送SYN+ACK包,并将半连接放入端口的积压队列中,虽然一般的主机都有超时机制和默认的重传次数,但是由于端口的半连接队列的长度是有限的,如果不断地向受害主机发送大量的TCP SYN报文,半连接队列就会很快填满,服务器拒绝新的连接,将导致该端口无法响应其他机器进行的连接请求,最终使受害主机的资源耗尽。
image图1 SYN Flooding攻击示意图
目前在防御SYN Flooding攻击方面有2种比较有效的技术。
(1)SYN-cookie技术
一般情况下,当服务器收到一个TCP SYN报文后,马上为该连接请求分配缓冲区,然后返回一个SYN+ACK报文,这时形成一个半连接。SYN Flooding正是利用了这一点,发送大量的伪造源地址的SYN连接请求,而不完成连接。这样就大量地消耗服务器的资源。
SYN-cookie技术针对标准TCP连接建立过程资源分配上的这一缺陷,改变了资源分配的策略。当服务器收到一个SYN报文后,不立即分配缓冲区,而是利用连接的信息生成一个cookie,并将这个cookie作为将要返回的SYN+ACK报文的初始序列号。当客户端返回一个ACK报文时,根据包头信息计算cookie,与返回的确认序列号(初始的序列号+1)的前24位进行对比,如果相同,则是一个正常连接,然后,分配资源,建立连接。
该技术的巧妙之点在于避免了在连接信息未完全到达前进行资源分配,使SYN Flooding攻击的资源消耗失效。实现的关键之处在于cookie的计算。cookie的计算应该做到包含本次连接的状态信息,使攻击者不能伪造cookie。cookie的计算过程如下。
服务器收到一个SYN包后,计算一个消息摘要mac:
mac = MAC(A,k)
MAC是密码学中的一个消息认证码函数,也就是满足某种安全性质的带密钥的hash函数,它能够提供cookie计算中需要的安全性。A为客户和服务器双方的IP地址和端口号以及参数t的串联组合:A = SOURCE_IP || SOURCE_PORT || DST_IP || DST_PORT || t;K为服务器独有的密钥;时间参数t为32比特长的时间计数器,每64秒加1;
生成cookie:
cookie = mac(0:24):表示取mac值的第0到24比特位;
设置将要返回的SYN+ACK报文的初始序列号,设置过程如下:
· 高24位用cookie代替;
· 接下来的3比特位用客户要求的最大报文长度MMS代替;
· 最后5比特位为t mod 32。
客户端收到来自服务器SYN+ACK报文后,返回一个ACK报文,这个ACK报文将带一个cookie(确认号为服务器发送过来的SYN ACK报文的初始序列号加1,所以不影响高24位),在服务器端重新计算cookie,与确认号的前24位比较,如果相同,则说明未被修改,连接合法,然后,服务器完成连接的建立过程。
SYN-cookie技术由于在连接建立过程中不需要在服务器端保存任何信息,实现了无状态的三次握手,从而有效地防御了SYN Flooding攻击。但是该方法也存在一些弱点。由于cookie的计算只涉及了包头的部分信息,在连接建立过程中不在服务器端保存任何信息,所以失去了协议的许多功能,比如超时重传。此外,由于计算cookie有一定的运算量,增加了连接建立的延迟时间,因此,SYN-cookie技术不能作为高性能服务器的防御手段。通常采用动态资源分配机制,即分配了一定的资源后再采用cookie技术,Linux系统中的SYN-cookie就是这样实现的。还有一个问题是,当我们避免了SYN Flooding攻击的同时,也提供了另一种拒绝服务攻击方式,攻击者发送大量的ACK报文,使服务器忙于计算验证。尽管如此,在预防SYN Flooding攻击方面,SYN-cookie技术仍然是一种有效的技术。
(2)地址状态监控的解决方法
地址状态监控的解决方法是利用监控工具对网络中的有关TCP连接的数据包进行监控,并对监听到的数据包进行处理。处理的主要依据是连接请求的源地址。
每个源地址都有一个状态与之对应,总共有四种状态:
· 初态:任何源地址刚开始的状态;
· NEW状态:第一次出现或出现多次也不能断定存在的源地址的状态;
· GOOD状态:断定存在的源地址所处的状态;
· BAD状态:源地址不存在或不可达时所处的状态。
具体的动作和状态转换根据TCP头中的位码值决定。
监听到SYN包,如果源地址是第一次出现,则置该源地址的状态为NEW状态;如果是NEW状态或BAD状态;则将该包的RST位置1然后重新发出去,如果是GOOD状态不作任何处理。
监听到ACK或RST包,如果源地址的状态为NEW状态,则转为GOOD状态;如果是GOOD状态则不变;如果是BAD状态则转为NEW状态;如果是BAD状态则转为NEW状态。
监听到从服务器来的SYN ACK报文(目的地址为addr),表明服务器已经为从addr发来的连接请求建立了一个半连接,为防止建立的半连接过多,向服务器发送一个ACK包,建立连接,同时,开始计时,如果超时,还未收到ACK报文,证明addr不可达,如果此时addr的状态为GOOD则转为NEW状态;如果addr的状态为NEW状态则转为BAD状态;如果为addr的状态为BAD状态则不变。
地址状态的转换图如图2所示。
image图2 地址状态转换图
下面分析一下基于地址状态监控的方法如何能够防御SYN Flooding攻击。
对于一个伪造源地址的SYN报文,若源地址第一次出现,则源地址的状态为NEW状态,当监听到服务器的SYN+ACK报文,表明服务器已经为该源地址的连接请求建立了半连接。此时,监控程序代源地址发送一个ACK报文完成连接。这样,半连接队列中的半连接数不是很多。计时器开始计时,由于源地址是伪造的,所以不会收到ACK报文,超时后,监控程序发送RST数据包,服务器释放该连接,该源地址的状态转为BAD状态。之后,对于每一个来自该源地址的SYN报文,监控程序都会主动发送一个RST报文。
对于一个合法的SYN报文,若源地址第一次出现,则源地址的状态为NEW状态,服务器响应请求,发送SYN+ACK报文,监控程序发送ACK报文,连接建立完毕。之后,来自客户端的ACK很快会到达,该源地址的状态转为GOOD状态。服务器可以很好地处理重复到达的ACK包。
3. ACK Flooding
ACK Flooding攻击是在TCP连接建立之后,所有的数据传输TCP报文都是带有ACK标志位的,主机在接收到一个带有ACK标志位的数据包的时候,需要检查该数据包所表示的连接四元组是否存在,如果存在则检查该数据包所表示的状态是否合法,然后再向应用层传递该数据包。如果在检查中发现该数据包不合法,例如该数据包所指向的目的端口在本机并未开放,则主机操作系统协议栈会回应RST包告诉对方此端口不存在。
这里,服务器要做两个动作:查表、回应ACK/RST。这种攻击方式显然没有SYN Flooding给服务器带来的冲击大,因此攻击者一定要用大流量ACK小包冲击才会对服务器造成影响。按照我们对TCP协议的理解,随机源IP的ACK小包应该会被Server很快丢弃,因为在服务器的TCP堆栈中没有这些ACK包的状态信息。但是实际上通过测试,发现有一些TCP服务会对ACK Flooding比较敏感,比如说JSP Server,在数量并不多的ACK小包的打击下,JSP Server就很难处理正常的连接请求。对于Apache或者IIS来说,10kbps的ACK Flooding不会构成危胁,但是更高数量的ACK Flooding会造成服务器网卡中断频率过高,负载过重而停止响应。可以肯定的是,ACK Flooding不但可以危害路由器等网络设备,而且对服务器上的应用有不小的影响。
如果没有开放端口,服务器将直接丢弃,这将会耗费服务器的CPU资源。如果端口开放,服务器回应RST。
利用对称性判断来分析出是否有攻击存在。所谓对称性判断,就是收包异常大于发包,因为攻击者通常会采用大量ACK包,并且为了提高攻击速度,一般采用内容基本一致的小包发送。这可以作为判断是否发生ACK Flooding的依据,但是目前已知情况来看,很少有单纯使用ACK Flooding攻击,通常都会和其他攻击方法混合使用,因此,很容易产生误判。
一些防火墙应对的方法是:建立一个hash表,用来存放TCP连接“状态”,相对于主机的TCP协议栈实现来说,状态检查的过程相对简化。例如,不作sequence number的检查,不作包乱序的处理,只是统计一定时间内是否有ACK包在该“连接”(即四元组)上通过,从而“大致”确定该“连接”是否是“活动的”。
4. UDP Flooding
UDP Flooding是日渐猖厥的流量型DoS攻击,原理也很简单。常见的情况是利用大量UDP小包冲击DNS服务器,或Radius认证服务器、流媒体视频服务器。100kbps的UDP Flooding经常将线路上的骨干设备例如防火墙打瘫,造成整个网段的瘫痪。由于UDP协议是一种无连接的服务,在UDP Flooding攻击中,攻击者可发送大量伪造源IP地址的小UDP包。但是,由于UDP协议是无连接性的,所以只要开了一个UDP的端口提供相关服务的话,那么就可针对相关的服务进行攻击。
正常应用情况下,UDP包双向流量会基本相等,而且大小和内容都是随机的,变化很大。出现UDP Flooding的情况下,针对同一目标IP的UDP包在一侧大量出现,并且内容和大小都比较固定。
UDP协议与TCP 协议不同,是无连接状态的协议,并且UDP应用协议五花八门,差异极大,因此针对UDP Flooding的防护非常困难。其防护要根据具体情况对待。
· 判断包大小:如果是大包攻击则使用防止UDP碎片方法。根据攻击包大小设定包碎片重组大小,通常不小于1500。在极端情况下,可以考虑丢弃所有UDP碎片。
· 攻击端口为业务端口:根据该业务UDP最大包的长度设置检测UDP最大包以过滤异常流量。
· 攻击端口为非业务端口:一个是丢弃所有UDP包,可能会误伤正常业务;另一个是建立UDP连接规则,要求所有去往该端口的UDP包,必须首先与TCP端口建立TCP连接。不过这种方法需要很专业的防火墙或其他防护设备支持。
在网络的关键之处使用防火墙对来源不明的有害数据进行过滤,可以有效减轻UDP Flooding攻击。此外,在用户的网络中还应采取如下的措施。
· 禁用或过滤监控和响应服务。
· 禁用或过滤其他的 UDP 服务。
· 如果用户必须提供一些 UDP 服务的外部访问,那么需要使用代理机制来保护那种服务,保证它不会被滥用。
· 对用户的网络进行监控以了解哪些系统在使用这些服务,并对滥用的迹象进行监控。
· 对于一些小型的服务器,可以直接用防火墙添加规则的方法屏蔽掉。
5. Connection Flooding
Connection Flooding是典型的并且非常的有效的利用小流量冲击大带宽网络服务的攻击方式,这种攻击方式目前已经越来越猖獗。这种攻击的原理是利用真实的IP地址向服务器发起大量的连接,并且建立连接之后很长时间不释放,占用服务器的资源,造成服务器上残余连接(WAIT状态)过多,效率降低,甚至资源耗尽,无法响应其他客户所发起的连接。
其中一种攻击方法是每秒钟向服务器发起大量的连接请求,这类似于固定源IP的SYN Flooding攻击,不同的是采用了真实的源IP地址。通常这可以在防火墙上限制每个源IP地址每秒钟的连接数来达到防护目的。但现在已有工具采用慢速连接的方式,也即几秒钟才和服务器建立一个连接,连接建立成功之后并不释放并定时发送垃圾数据包给服务器使连接得以长时间保持。这样一个IP地址就可以和服务器建立成百上千的连接,而服务器可以承受的连接数是有限的,这就达到了拒绝服务的效果。
另外,蠕虫大规模爆发的时候,由于蠕虫代码比较简单,传播过程中会出现大量源IP地址相同的包,对于 TCP 蠕虫,则表现为大范围扫描行为。这是在判断Connection Flooding时需要注意的。
该攻击的一般表现形式是:在受攻击的服务器上使用netstat –an命令来查看,会发现大量连接状态来自少数的几个源。如果统计的话,可以看到连接数对比平时出现异常。并且增长到某一阈值之后开始波动,说明此时可能已经接近性能极限。因此,对这种攻击的判断原则为:在流量上体现并不大,甚至可能会很小;出现大量的ESTABLISH状态;新建的ESTABLISH状态总数有波动。
防范该攻击主要有如下方法。
· 主动清除残余连接。
· 对恶意连接的IP进行封禁。
· 限制每个源IP的连接数。
· 可以对特定的URL进行防护。
· 反查Proxy后面发起HTTP Get Flood的源。