Sep 112009
 

在本月的周二补丁日,微软发布了一组补丁用于修复存在于TCP/IP协议栈上的漏洞。可以从http://www.microsoft.com/technet/security/bulletin/MS09-048.mspx看到微软的更新声明。

同时,Cisco也发布了用于解决存在于IOS同样漏洞的补丁,声明于此http://www.cisco.com/warp/public/707/cisco-sa-20090908-tcp24.shtml

发布补丁其实并没什么稀奇的,特地为这个漏洞/补丁写一篇Blog的原因是这个漏洞背后有点非常有意思的八卦:

  • 这个漏洞能造成的影响其实相当巨大,当初问题被发现时,非常多的TCP/IP协议栈实现都被证明是存在问题的。而在接下来的一段时间内,发现这个问题的几个人开发了一个攻击工具,经证明可以对Windows/Linux/BSD等等的机器发起攻击,仅仅需要发起数kbps的流量,持续几分钟之后就会导致目标服务器完全停止响应。
  • 可被攻击的目标非常广泛,任何有端口在监听的服务器、PC甚至路由器都会被攻击。
  • 实际这个问题属于协议的设计缺陷,所以当发现者公布这个问题时,他们没有使用漏洞(Vulnerability)这个词,而是使用了瑕疵(Flaw)。
  • 厂商们对此问题的反应是承认此瑕疵存在,但因为对其修补需要反复的研究论证后才可能实现,因此拖了相当久的时间。Linux似乎挺早就做了相应的修补措施,但MS和Cisco却花了一年多直到今天才真正去修复这个瑕疵。以至于发现者其一还没有熬到这个问题修复就已经驾鹤西去。

其实这个问题的原理并不是很复杂,它起源于针对SYN Flood的解决方案SYN Cookie,对于SYN Flood/SYN Cookie不了解的人可以先补补课,这里有篇不错的文章:http://www.ibm.com/developerworks/cn/linux/l-syncookie/index.html

简单说,SYN Flood是因为攻击者发送虚假的SYN包而本身不做其他任何多余的工作,而被攻击者在接收到SYN后需要进行一系列建立Session、分配内存等资源分配的操作,导致攻击者可以用极小的代价耗尽被攻击者的所有资源,从而达到DoS(Denial of Service)的效果。而SYN Cookie则使服务器在接到SYN后并不立即进行资源分配,而是将SourceIP:SourcePort – DestinationIP:DestinationPort的4元组通过某稍微复杂但又不怎么消耗资源的算法转换得到一个值放入SYN/ACK的ISN中发送出去(称作Cookie)。此时真正的客户会响应这个SYN/ACK并在发回的ACK再次包含这个Cookie,服务器通过验证Cookie和四元组是否对应来判断客户是否合法后,才进行资源的分配工作。伪造SYN的攻击者因为无法收到或者猜出Cookie,无法完成三次握手,也就达成不了DoS的效果了。

而这个TCP/IP协议栈的瑕疵的思路是将SYN Cookie的思路用于攻击,客户端本身不消耗资源,也不维护连接状态,通过在发送的包中加入Cookie来辨识服务器,通过构建特定包使服务器完成三次握手,完成后服务器必然开始分配连接所需要的资源,例如维持连接状态表,分配内存,定时器。在此之后攻击者发送0窗口的ACK通知服务器这一端没有足够的buffer来传输数据,这样服务器就会持续维持此连接,并分配定时器定时来探测攻击者的窗口是否打开。此时攻击者所要做的只是间隔一定时间内继续发送0窗口包告诉服务器继续维持连接,但攻击者本身仍机不需要消耗任何资源。反复此过程多次,服务器中将会有多个持续的连接,虽无数据传输,但服务器本身需要维持这些链接,并还需要不时触发定时器来探测窗口,导致服务器的协议栈资源被大大消耗,到达一定程度后,服务器会因为资源耗尽而停止响应。

问题的发现者撰写了很详细的资料用于描述这个问题,我将个人认为非常不错的一个PPT放到Google Docs上供大家研究,Sockstress是作者开发出来验证这个漏洞可以被利用造成DoS的工具:

作者的主页上还有更多的资料可供研究:http://sockstress.com/

目前这个漏洞在这一年内究竟有多少真正实现DoS的案例还没有统计资料,个人认为应该有不少实际被攻击成功的例子,但只是没有广泛引起关注而已。

对于此问题的修复,MS和Cisco都没有披露补丁的原理,个人猜测是加强对于恶意空置连接的检测,并强制对端如果持续0窗口一段时间后强行关闭连接并释放资源。因为协议RFC本身并未对此作出强制或建议规定,各厂商的协议栈实现可能会有所不同。就像SYN Cookie当初的情况一样,实现本身对RFC的要求有所相违背,但为了保护协议栈本身却不得不做出此类抉择,估计这也是厂商拖了这么久才真正放出补丁的原因之一吧。不知以后的RFC中是否对比会有所补充。

说了这么多东西,其实我个人并不是对这个漏洞的实现细节特别感兴趣,只是刚好最近这个事儿比较热门,而我工作上上维护的某个Service的程序设计行为与这个漏洞的原理有非常大的共通之处。程序本身的行为对协议栈造成了很大的压力,刚好最近流量突增,使得部分服务器过载而开始间歇性罢工,一帮兄弟们在焦头烂额的想办法修,所以实在是想对这个漏洞吐个槽。程序本身的行为设计时就没考虑周全,流量增加到Server撑不住才想办法修,对于运营人员来说,实在不是什么令人爽得起来的事,

最后附送一个SLashdot上对这个事儿讨论的链接:http://it.slashdot.org/story/09/09/08/1839258/Microsoft-Cisco-Finally-Patch-TCP-DoS-Flaw,其实这个站上的人们也挺有娱乐精神的,吵着吵着就跑题,甚至连Windows NT最早某些工具用了BSD协议代码的那些旧八卦也挖出来了。无聊时看看还真提神-_-