安全手记:Netscape败于我手 张弋(编译) 1998年 第02期 08版   安全性一直是互联网上最引人注目的问题之一,尤其是在网上交易日益盛行的今天,需要通过互联网络将客户的信用卡帐号、密码等个人信息上传到商业服务器中,这无疑是黑客们关注的焦点。因此各大公司都提出了一些解决方案,力图使自己成为安全协议标准,从而在电子货币交易这一庞大市场中占据有利地位。Netscape便在自己的各种产品中力推被称为“安全套接层”(SSL)的加密传输协议,两位来自加州大学伯克利分校计算机系的博士生伊安和戴维善意地发现了它的漏洞,并促使了Netscape浏览器升级。 #1在SSL外壳上找一条缝   Netscape推出SSL后,我们决定仔细研究它的执行机制,结果我们的研究暴露了SSL执行中的重大缺陷,它使得一个窃取者能够相当容易的解码加密后的通信信息,也就是说,我们突破了Netscape的安全防线,你将会看到,这并不是很困难的事。   SSL用很大的一个随机数作为密钥来加密信息。通常这样的密钥只有发送和接收的双方才知道,其安全是建立在“不可能尝试所有的密钥值”的基础上的。   如果一个攻击者能够预见到密钥值(像“蠕虫”一样用一些最可能的单词来猜测),或将必须尝试的密钥数大大降低了,长随机密钥的效果就会在很大程度上打了折扣。因此,攻击者最感头疼的莫过于密钥是由不预定的随机数源产生的。   然而“随机”不是一个简单的问题:谁能说某一串数比另一串数更随机?真正的随机数源来自于那些物理现象,例如一种元素的放射性衰变的实时速率,或者半导体真空二极管的热噪声。与这些东西不同,CPU的状态总是确定的,计算机不可能产生真正意义上的随机数。人们通过一些算法来产生“随机数”,在各种高级语言中也大都提供了一个“随机函数”,但我们可以注意到这些算法和函数都必须先选定一个“种子值”,然后产生一个“随机序列”。实际上一旦这个种子确定了,算法产生的序列中的每个值也都被定下来了,它们只是一种伪随机序列罢了。为了提高伪随机序列的随机性,程序员通常是让这个种子取自流逝的时间值,我们愉快地发现,Netscape的程序员也正是这么做的。   选择种子值的方式应当成为像SSL这样的加密协议的重要环节。如果一个种子值能够被猜出来,或者被确定在一个较小的集合中,攻击者要做的事就容易多了。   由于Netscape不会透露程序中这一部分的细节,我们只好反编译现有几种版本的Netscape浏览器的执行文件,用这种枯燥无味的“逆向工程”,我们得到了Netscape产生随机种子、用种子产生随机数和用随机数产生密钥的算法。现在,我们要做的只是确定这个种子值,这就是SSL外壳上的一条缝。 #1攻击、攻击、再攻击   对于Netscape来说不怎么走运的是,美国政府禁止输出具有强加密技术的产品。为了发行自己浏览器的国际版本,Netscape不得不降低加密强度,只使用40比特长度的密钥,也就是说有一万亿种可能的密钥值。也许这听起来是一个很大的数,但是要不了多少人联合起来,就能够在30小时以内试遍每一个可能的值;在出口法令修改之前,绝大多数人使用的Netscape浏览器都是这种国际版本。但我们不采用这种蛮力进攻的方法,我们将进行更智能化的攻击。在这里我们只讨论攻击Netscape浏览器的UNIX版本,因为UNIX版本产生随机数的过程使用了更随机的量,使它更难以被攻破。   在UNIX版本的Netscape浏览器中,随机种子与流逝的时间的秒、微秒、进程ID、父进程ID相关,每一个可能的时间值、进程ID和父进程ID都对应一个唯一的种子值,进而产生一个与之唯一对应的密钥。   我们先假设攻击者在运行Netscape浏览器的UNIX主机上有一个帐户。他能够使用PS命令相当容易的发现浏览器的进程ID和父进程ID,这个命令会列出系统中所有进程的进程ID值。   剩下的事就是猜出时间值。绝大多数流行的以太网侦测工具(包括TCP dump)都会记录下每个协议包的正确时间。因此攻击者能够猜出Netscape浏览器使用的时间值并将之精确到1秒以内。这样就获得了产生随机种子的秒值。   在产生种子所使用的四个变量“秒、微秒、进程ID、父进程ID”中,我们已经知道了其中三个,只有微秒仍然是未知数。然而它仅有一百万种可能的值。在一台HP 712/80的机器上尝试全部一百万个可能值只花了我们大约25秒钟。   我们的第二次攻击假设攻击者没有被攻击的UNIX主机上的帐户,这意味着进程ID和父进程ID都是未知的了。然而,这些量还是能够得到的,有几个巧妙的技巧能够用来发现它们。   对任何加密系统最通用的也最天真的攻击方法是强制尝试所有可能的密钥值,但对Netscape浏览器的美国国内版本来说,尝试所有可能的128比特密钥是绝对不可能的。然而,Netscape产生种子机制的漏洞使得可以通过尝试几个关键值来加速这一过程。从前面的描写中我们可以看到程序设计人员的那些乐观主义的作法将甚至允许一个远程攻击者在几分钟内突破Netscape的安全防线。 #1教训与忠告   在我们宣布这些攻击之后,Netscape很快以一个新版本来响应。由于只有老版本才是脆弱的,我们的攻击直接的、长期的影响将是微乎其微的,但也许更重要的是我们应吸取一些教训。   加密通信领域早就认识到产生随机数是需要相当谨慎的,但同时又易陷于拙劣之中;Netscape带着几分痛苦得到了这个教训。如果你是因为加密的目的产生随机数,一定要非常小心。   一般来说,从一个程序的外部来观察它的内部的行为是相当困难的,但这绝非不可能。一旦你的算法“真相大白”,长随机密钥便是你的最后一道防线,不要让别人像绕过马其诺防线一样绕过它。记住:在黑暗中,总有眼睛在窥探……