配置和使用密码安全协议
TCP的初始序列号并没有提供防范连接攻击的相应措施。TCP的头部缺少加密选项用于强加密认证,于是,一种叫做IPSec的密码安全协议的技术提出了。IPSec提供了一种加密技术(End to end cryptographic),使系统能验证一个包是否属于一个特定的流。这种加密技术是在网络层实现的。其它的在传输层实现的解决方案(如SSL/TLS和SSH1/SSH2), 只能防止一个无关的包插入一个会话中,但对连接重置(拒绝服务)却无能为力,原因是因为连接处理是发生在更低的层。IPSec能够同时应付着两种攻击(包攻击和连接攻击)。它直接集成在网络层的安全模型里面。
上面的解决方案并不需要对TCP协议做任何得修改,RFC2385(“基于TCP MD5签名选项的BGP会话保护)和其他的技术提供了增加TCP头部的密码保护,但是,却带来了收到拒绝服务攻击和互操作性和性能方面的潜在威胁。使用加密安全协议有几个优于其它方案的地方。TCP头部加密防止了Hijacking和包扰乱等攻击行为,而TCP层仍然能够提供返回一个简单增加ISN的机制,使方案提供了最大程度的可靠性。但实现IPSec非常复杂,而且它需要客户机支持,考虑到可用性,许多系统都选择使用RFC 1948。
使用RFC1948
在RFC1948中,Bellovin提出了通过使用4-tuples的HASH单向加密函数,能够使远程攻击者无从下手(但不能阻止同一网段的攻击者通过监听网络上的数据来判断ISN)。
Newsham 在他的论文 [ref_newsham]中提到:
RFC 1948 [ref1]提出了一种不容易攻击(通过猜测)的TCP ISN的生成方法。此方法通过连接标识符来区分序列号空间。每一个连接标识符由本地地址,本地端口,远程地址,远程端口来组成,并由一个函数计算标识符分的序列号地址空间偏移值(唯一)。此函数不能被攻击者获得,否则,攻击者可以通过计算获得ISN。于是,ISN就在这个偏移值上增加。ISN的值以这种方式产生能够抵受上面提到的对ISN的猜测攻击。
一旦全局ISN空间由上述方法来生成,所有的对TCP ISN的远程攻击都变得不合实际。但是,需要指出的,即使我们依照RFC 1948来实现ISN的生成器,攻击者仍然可以通过特定的条件来获得ISN(这一点在后面叙述).
另外,用加密的强哈希算法(MD5)来实现ISN的生成器会导致TCP的建立时间延长。所以,有些生成器(如Linux
kernel )选择用减少了轮数的MD4函数来提供足够好的安全性同时又把性能下降变得最低。削弱哈希函数的一个地方是每几分钟就需要对生成器做一次re-key 的处理,经过了一次re-key的处理后,安全性提高了,但是,RFC793提到的可靠性却变成另一个问题。
我们已经知道,严格符合RFC1948的ISN生成方法有一个潜在的危机:
一个攻击者如果以前合法拥有过一个IP地址,他通过对ISN进行大量的采样,可以估计到随后的ISN的变化规律。在以后,尽管这个IP地址已经不属于此攻击者,但他仍然可以通过猜测ISN来进行IP欺骗。
以下,我们可以看到RFC 1948的弱点:
ISN = M + F(sip, sport, dip, dport, )
其中
ISN 32位的初始序列号
M 单调增加的计数器
F 单向散列哈希函数 (例如 MD4 or MD5)
sip 源IP地址
sport 源端口
dip 目的IP地址
dport 目的端口
哈希函数可选部分,使远程攻击者更难猜到ISN.
ISN自身的值是按照一个常数值稳定增加的,所以F()需要保持相对的稳定性。而根据Bellovin 所提出的,是一个系统特定的值(例如机器的启动时间,密码,初始随机数等),这些值并不 会经常变。
但是,如果Hash函数在实现上存在漏洞(我们无法保证一个绝对安全的Hash函数,况且,它的实现又与操作系统密切相关),攻击者就可以通过大量的采样,来分析,其中,源IP地址,源端口,目的IP地址,目的端口都是不变的,这减少了攻击者分析的难度。
Linux TCP的ISN生成器避免了这一点。它每5分钟计算一次值,把泄漏的风险降到了最低。
有一个办法可以做的更好:
取M = M + R(t)
ISN = M + F(sip, sport, dip, dport, )
其中
R(t) 是一个关于时间的随机函数
很有必要这样做,因为它使攻击者猜测ISN的难度更大了(弱点在理论上还是存在的)。
其它一些方法
构造TCP ISN生成器的一些更直接的方法是:简单地选取一些随机数作为ISN。这就是给定一个32位的空间,指定
ISN = R(t)。(假设R()是完全的非伪随机数生成函数)
固然,对于完全随机的ISN值,攻击者猜测到的可能性是1/232是,随之带来的一个问题是ISN空间里面的值的互相重复。这违反了许多RFC(RFC 793, RFC 1185, RFC 1323, RFC1948等)的假设----ISN单调增加。这将对TCP协议的稳定性和可靠性带来不可预计的问题。
其它一些由Niels Provos(来自OpenBSD 组织)结合完全随机方法和RFC 1948解决方案:
ISN = ((PRNG(t))
32位
其中
PRNG(t) :一组随机指定的连续的16位数字
0x00000000 -- 0xffff0000
R(t) :16位随机数生成器(它的高位msb设成0)0x00000000 -- 0x0000ffff
上面的公式被用于设计OpenBsd的ISN生成器,相关的源代码可以从下面的网址获得
http://www.openbsd.org/cgi-bin/cvsweb/src/sys/netinet/tcp_subr.c
Provos的实现方法有效地生成了一组在给定时间内的不会重复的ISN的值,每两个ISN值都至少相差32K,这不但避免了随机方法造成的ISN的值的冲突,而且避免了因为哈希函数计算带来的性能上的下降,但是,它太依赖于系统时钟,一旦系统时钟状态给攻击者知道了,就存在着系统的全局ISN状态泄密的危机。
TCP ISN生成器的构造方法的安全性评估
ISN与PRNGs(伪随机数生成器)
我们很难用一台计算机去生成一些不可预测的数字,因为,计算机被设计成一种以重复和准确的方式去执行一套指令的机器。所以,每个固定的算法都可以在其他机器上生成同样的结果。如果能够推断远程主机的内部状态,攻击者就可以预测它的输出;即使不知道远程主机的PNRG函数,但因为算法最终会使ISN回绕,按一定的规律重复生成以前的ISN,所以,攻击者仍然可以推断ISN。幸运的是,目前条件下,ISN的重复可以延长到几个月甚至几年。但是,仍然有部分PRNG生成器在产生500个元素后就开始回绕。解决伪随机数的方法是引入外部随机源,击键延时,I/O中断,或者其它对攻击者来说不可预知的参数。把这种方法和一个合理的HASH函数结合起来,就可以产生出32位的不可预知的TCP ISN的值,同时又隐蔽了主机的PNRG的内部状态。不幸的是,很少的TCP ISN产生器是按这种思路去设计的,但即使是这样设计的产生器,也会有很多的实现上的漏洞使这个产生器产生的ISN具有可猜测性。
RFC1948的建议提供了一种比较完善的方法,但是,对攻击者来说,ISN仍然存在着可分析性和猜测性。其中,PRNG的实现是个很关键的地方。
Spoofing 集合
需要知道一点是,如果我们有足够的能力能够同时可以发出232个包,每个包由不同的ISN值,那么,猜中ISN的可能性是100%。但是,无论从带宽或计算机的速度来说都是不实际的。但是,我们仍然可以发大量的包去增加命中的几率,我们把这个发出的攻击包的集合称为Spoofing集合。通常,从计算机速度和网络数据上传速率两方面来考虑,含5000个包的Spoofing的集合对众多的网络用户是没有问题的,5000-60000个包的Spoofing集合对宽带网的用户也是不成问题的,大于60000个包的Spoofing集合则超出一般攻击者的能力。网络的速度和计算机性能的不断增加会提高那种使用穷尽攻击方法猜测ISN的成功率。从攻击者的立场,当然希望能够通过定制一个尽可能小的Spoofing集合,而命中的几率又尽可能高。我们假定我们攻击前先收集50000个包作为ISN值的采样,然后,我们把这些ISN用作对将来的ISN的值猜测的依据。
一种称为“delay coordinates”的分析方法
在动态系统和非线性系统中,经常使用一种叫做“delay coordinates”的分析法,这种方法使我们可以通过对以前的数据的采样分析来推想以后的数据。
我们试图以建立一个三维空间(x,y,z)来观察ISN值(seq[t])的变化,其中t取0,1,2, ……
(图6)
方程组(E1)
现在,对采样了的50000个ISN序列seq[t] 按照上面的三个方程式来构建空间模型A。这样,就可以通过A的图像特征来分析这个PNRG生成的ISN值的规律。A呈现的空间模型的3D特性越强,它的可分析性就越好。
接着,我们根据这个模型,去分析下一个ISN值seq[t],为此,我们用一个集合K(5000个)去猜测seq[t]。
如果我们知道seq[t-1],要求seq[t],那么,可以通过在这个三维空间中找出一个有良好特性的节点P(x,y,z),将P.x+seq[t-1],我们就可以得到seq[t]。现在,我们将注意力放到怎样在这个三维空间中选择一些点来构成Spoofing集合,也就是怎样通过seq[t-1],seq[t-2],sea[t-3]来推知