OpenSSL必死无疑,永远不会有改善

jopen 10年前

OpenSSL软件包大概有30万行代码,这意味着其中可能仍然存在着大约299个bug,现在就是心脏出血的bug — 这使得几乎任何人都可以检查其通常无权被访问的内部状态 — 它已经被修复了.

这的确是所有你需要知道的,但你也得清除,这不会让我消停下来,是不?

理论上要确保一个计算机网络连接的安全并不真的很艰难. 首先你可以让技术过硬的密码学专家设计一些加密的构造块. 你将会需要一个好的散列功能,一个好的对称加密算法,以及一个好的非对称加密算法. 接下来你可以让技术过硬的加密协议设计者来定义这些构造块如何以一种极为详尽的方式捆绑在一起. 然后是一个技术过硬的API设计者来定义应用程序如何通过一个带有精心选择的可靠的默认值,以及一个好的错误报告机制的,深思熟虑并且具有容错机制的API,访问到协议. 然后是让技术过硬的程序员根据API完成对算法和协议高质量的编码实现,并且全部通过分析和审核. 而在此之后,应用程序的开发者 - 他们可以是任何什么人,但通常都技术过硬 - 最后会写段代码来打开一个受保护的连接.

但我们的事情还没完呢.

我们需要确保编译器将高级语言写就的代码正确的翻译成机器语言指令. 而这之后技术过硬的编译器开发者才能做到啊! 我们还需要确保计算环境值得信任 — 系统库和操作系统内核中不能有漏洞,错误,后门,或者恶意软件. 而这又该由谁来负责呢? 你答对了,很明显该是技术过硬的内核开发人员!  而当然如果CPU不老老实实的去执行指令,所有这些全都白费, 技术过硬的CPU工程师无疑将发现这一点.

现在 — 直到最终 — 我们才可以保护将一张小猫图片从一台计算机到另一台计算机的传输.

这不是那么糟糕的,是不是呢?

如我所指定的这样一个梦之队也并不是完全无懈可击,就好像 OpenSSL 中会包含如下的代码:

/*   * The aim of right-shifting md_size is so that the compiler doesn't   * figure out that it can remove div_spoiler as that would require it   * to prove that md_size is always even, which I hope is beyond it.  * (向右移动md_size的目的是,由于编译器不会如我们所期望的考虑到它可以移除  * div_spoiler,这需要它先证明md_size总是偶数,我觉得这超出来它的处理能力)  */   div_spoiler = md_size >> 1;   div_spoiler <<= (sizeof(div_spoiler)-1)*8;   rotate_offset = (div_spoiler + mac_start - scan_start) % md_size;

老实说 — 在我向你指明这点之前,你会想到会有一个成熟的,正确的,经过编译器改善的安全风险吗?

你当然不会!它已经被证明是正确了的,对吧?

而那里就是我们的安全模型——如果你称它是安全模型的话——发生故障的地方.  这里涉及如此多的代码,因而如果出问题的话,没有人会有线索.

在我的计算机上面的数量大概是:

Operating system Kernel:        2.0 million lines of code   Compiler:                       2.0 --//--   C language runtime library:     0.5 --//--   Cryptolibrary:                  0.3 --//--

涉及到每一个额外的编程语言,都将增加大约一百万行. 使用一个图形用户界面技术是这个数量的两倍, 而一个浏览器则又会再翻倍. 一个合理的估计是你读这篇文章的电脑至少有100,但更可能是1000个漏洞,这些漏洞牺牲了你的安全性. 如果这些漏洞对于你的计算机而言是独特的,那还不会太糟糕。但实际情况却不是这样的,成百万成百万的计算机上都有完全相同的漏洞,并且每一个漏洞都有爆发的潜在可能. 还有 — 因为如果这利用漏洞的难度不够大的话 — 有些人会积极地尝试去对结果搞破坏,为的是使得“情报收集”更加的简单实惠. 显然我们的梦之队的一些技术过硬的工程师和科学家会有隐藏的动机 —  否则NSA的领导们就有点太无能了.

再就是证书颁发机构。他们的工作是充当“信任锚”,这样一旦你已经建立了一个安全连接,你也可以知道你是在和谁通信。

CA的可信性是一个笑话.

你会相信:

T&Uuml;RKTRUST BİLGİ İLETİŞİM VE BİLİŞİM G&Uuml;VENLİĞİ HİZMETLERİ A.Ş (T&Uuml;RKTRUST数据通信和信息安全服务,INC).

用它来认证进入你银行的连接吗?

你甚至不知道 "G&Uuml;VENLİĞİ HİZMETLERİ" 是什么意思,对吧?

我当然不会知道啥意思,而且我也不信任他们!

在 2012 年 8月, 他们发表了可以生成其持有者是Google的整数. T&Uuml;RKTRUST当然会宣称这完全只会是“一个一次性错误”,也就是说“不会涉及任何犯规的操作”,并且“它永远也不会再发生一次了”。

没有人会相信它的只言片语.

然而,你的浏览器可仍然默认是相信他们的,仅仅因为它相信其他或多或少的有嫌疑的机构是说实话的. 因此我们就使用一个带有臃肿漏洞的软件来进行链接,相信幕后有政府渗透的CA来确保我们在和谁通信?

肯定有更好的办法,对吗?

然而并没有更好的办法.

我们从来没有发现两个之前从来没打过交道的组织建立安全通信通道的更简单的办法. 一直到非对称加密 (1973-1977)被开发出来之前,这都被认为是不可能的.  而如果你想要知道谁在连接的另一端,唯一的办法是相信一个宣称知道这一信息的第三方机构. 没有什么数学或者加密领域上的突破会改变这个现状,因为我们的身份是社会结构,而不是物理实体.

因此,如果我们想要电子商务运作起来,我们就不得不去运行这些有缺陷的代码,而我们应该实现一些比"CA-黑手党"更加值得信任的东西。

而这又让我回到了OpenSSL — 它很烂. 代码糟糕透了,文档也存在误导, 而默认的东西都是在忽悠扯淡. 再加上其30万行代码使其承受这任何你可以想象得到的软件工程领域的痼疾:

  • 没有架构在中心的权威机构

  • 6,740 行 goto 语句

  • 内联汇编代码

  • 多种不同的编码风格

  • 宏预处理器的晦涩运用

  • 不一致的命名约定

  • 太多的选择和选项

  • 不能被理解的僵尸代码

  • 存在误导和不连贯的注释

如此种种.

而这不是任何人的错误.

没有人真正负责过 OpenSSL, 它也就成为了发明加密原型的默认垃圾清理场之类的东西, 而由于都是在光天化日之下 (就在你能发现如何使用它的某处)加密所有的东西, 它也成了机密功能的默认来源.

我敢肯定有不止一个人曾近想过“没有人会因为使用了OpenSSL而被解雇".

而这就是在我写下这篇文章的时候网上的每个人都会感到恐慌的原因.

这个漏洞是非常糟糕的,即便是作为OpenSSL中的漏洞, 而我在ACM Queue的合作专栏作家,  Kode Vicious, 曾近设法去寻找一线希望: "因为他们使用的是一个 '短' 整形, 只有64KB价值的秘密被曝光了."

而这不是第一个也不会是OpenSSL中最后一个严重的漏洞 , 而由于其永远都不会好转,OpenSSL 必死无疑.

我们需要一个设计良好的 API, 尽可能简单到使得人们很难去错误的使用它. 而我们需要针对这个API的具有独立品质的实现, 以便如果其中一个不行了,人们可以在几个小时之内切换到另外更好的一个.

到底是爱它还是讨厌他? 请让我们了解到吧。