图片由Waifu Diffusion v1.3(float16)生成——1girl,和服,动物穿越,喇叭,响亮的声音,铺天盖地,红色的天空,云朵,暴风雨,长发,紫发,黄色的眼睛,狐狸耳朵,粗线条,墨水轮廓,黑色轮廓
因此,OpenSSL 安全问题禁运今天结束,补丁也被删除了。基于安全问题的内容、在实践中利用它的难度,以及大多数 Linux 发行版都采取了基本的预防措施来防止它成为可行的攻击媒介这一事实:这个问题几乎不会影响 OpenSSL 中的任何用户。真实世界。
有关 CVE-2022-3786 和 CVE-2022-3602 的更多详细信息,请参阅 OpenSSL 团队题为CVE-2022-3786 和 CVE-2022-3602:X.509 电子邮件地址缓冲区溢出的帖子。
这对大多数人来说没什么大不了的主要原因是大多数现代编译器都启用了堆栈溢出保护,这将阻止此缓冲区溢出导致执行任意代码。在实践中,堆栈保护器会意识到有问题并导致程序爆炸。这将攻击从任意代码执行攻击减少到简单的拒绝服务攻击,这在实践中要无聊得多。
有关这方面的更多详细信息,请参阅这篇文章,该文章解释了这种攻击的工作原理,如何使用易受攻击的 OpenSSL 版本在家中复制它,以及最终为什么它不是一个实际问题。如果任何组织想要使用它,几乎肯定会导致证书在证书透明度日志中被注意到,然后可能会质疑整个证书颁发机构颁发证书的能力。这很可能最终导致不允许证书颁发机构颁发证书,直到允许该颁发机构颁发证书的情况得到修复并独立评估以修复。
我想它在具有自定义 TLS 根证书的环境中是最可行的,但在实践中这些证书很少见,无法真正使其成为一种有用的攻击机制。等式中有很多容易实现的目标。不过,也许人们真的非常不信任证书颁发机构。
对于我在博客上处理 OpenSSL 问题的方式,我感到有些不得不道歉。我相信 OpenSSL 团队的话,我觉得我做了正确的事情,即使它在实践中被证明是一个巨大的空想。如果我对这些问题的报道伤害了您或让您担心超出正常范围,我很抱歉。我正在脱离所提供的信息,并且我从几个来源听说过,我相信这是值得真正关心的事情。我将利用这段经历来帮助塑造我将来报告这些事情的方式。
为什么我很沮丧
关于这两个漏洞,有两件大事让我感到沮丧。
首先是 OpenSSL 团队显然不知道哪些编译器标志用于在流行的目标上编译 OpenSSL 。就像,我明白了,在某种程度上这是有道理的。 OpenSSL 用于十亿不同的环境,它们都是独特的雪花。
然而,在某种程度上,这感觉有点不可原谅。 Ubuntu 和 CentOS 是 OpenSSL 的一些最大用户。为 Canonical 和 Red Hat 工作的人是 OpenSSL 的贡献者。我觉得他们应该对最常见的环境做什么有一定的了解。当然,他们无法阻止帕劳的某些嵌入式设备对证书中电子邮件地址的指针进行 ACE,但我当然希望 Ubuntu 和 CentOS 是他们真正关心和验证的目标.
困扰我的第二件事是,在今天早些时候,即 2022 年 11 月 1 日,它似乎已从“关键”错误降级为“高”错误。为了让 OpenSSL 团队从怀疑中获得最大可能的好处,这是有点合理。当他们继续探究事物并研究人们的脆弱程度时,他们意识到他们对这个问题的初步评估是错误的。这意味着那些说情况非常糟糕的人准确地报告了他们当时的理解。在某种程度上,这就是科学过程的运作方式:你有一个假设,你测试它,你报告结果。只是令人沮丧的是花了这么长时间才降级它。我已经为一个严重的漏洞做好了准备,我相信其他人也是如此。
我担心这会被视为不像我们应该的那样乍一看认真对待“关键”披露的一个理由。必须将“严重”错误视为严重错误。从社区健康的角度来看,人们被告知一个非常糟糕的事情即将出现一个星期,然后把地毯从他们下面拉出来,现在是“不,我们错了,你可能还好”。
再次,这种情况发生了,他们改变主意是完全合理的。我只是担心这种程度的警报疲劳只是训练人们不把事情当回事,因为这次还不错。
事实证明,OpenSSL 公告比漏洞更具破坏性。
— dkp (@tweetdkp) 2022 年 11 月 1 日
NixOS 启用了堆栈保护,因此它从一开始就不会受到此问题的影响。不需要我的文章告诉人们用 OpenSSL 1.x 重新编译 nginx。然而,这是在 nixpkgs 中展示overrides
的一种很酷的方式,所以无论如何我都会认为这是一场胜利。
热点地带™️
也许我们需要停止在 C 中编写新的安全关键代码。以下是修复CVE-2011-3602的补丁之一的全部内容:
--- a/crypto/punycode.c +++ b/crypto/punycode.c @@ -181,7 +181,7 @@ int ossl_punycode_decode(const char *pEncoded, const size_t enc_len, n = n + i / (written_out + 1); i %= (written_out + 1); - if (written_out > max_out) + if (written_out >= max_out) return 0; memmove(pDecoded + i + 1, pDecoded + i,
对于那些不太了解 C 的人,这是我试图解释发生了什么的尝试。这是在将punycode文本解码为其对应的 Unicode 文本的函数中。它所做的一件事是从输入缓冲区复制数据,对其进行解码,然后将结果放入输出缓冲区。这个 if 语句是为了防止缓冲区溢出并进入接下来的任何内容。如果“接下来发生的事情”在堆栈中,则该值可能会溢出,然后该值将成为调用该函数时的返回地址。
其根本原因是对输出缓冲区的一次越界写入。这之所以成为可能,是因为 C 没有办法让你静态地证明你不能像这样覆盖缓冲区,这样编译器就会拒绝编译代码。
也许作为一个行业,我们需要开始更加认真地对待形式验证、内存安全和相关的事情。也许将 Rust 添加到 Linux 内核是一件好事。 Rust 最近也被添加到 Windows 内核中,而没有人真正注意到它的存在。