SSLChina
- 关注
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
知名且广泛使用的加密库 OpenSSL本周早些时候发布了一个安全补丁。
对于那些喜欢简洁、现代、无衬线字体的人来说,令人讨厌的是,新版本是OpenSSL 1.1.1l,如果您使用大写 EYE、小写 ELL 和数字 ONE 看起来都相似的字体,则很难解释。
用语音拼写出来,你是在OpenSSL version ONE dot ONE dot ONE LIMA
.
(在撰写本文时,Naked Security 的官方字体是Flama,这是一种源自 DIN 1451 的包豪斯风格字体系列,它本身源于 20 世纪早期的德国铁路和公路字体风格。我们的小写 ELL 有一个整洁的向右卷曲在底部以提高其易读性,而 ONE 则具有经典的欧洲外观,底部有横杆,顶部有一点向左轻弹。但并非所有字体都是这样制作的。)
错误
OpenSSL,顾名思义,主要由使用 TLS 协议(传输层安全)的网络软件使用,以前称为 SSL(安全套接字层),以保护传输中的数据。
尽管 TLS 现在已经取代了 SSL,一路上消除了大量的密码缺陷,但许多支持它的流行开源编程库,如 OpenSSL、LibreSSL 和 BoringSSL,为了熟悉起见,保留了老派的产品名称.
尽管将 TLS 支持作为其主要目标,OpenSSL 还允许您访问 TLS 本身所依赖的较低级别的功能,因此您可以使用libcrypto
OpenSSL的一部分进行独立加密、计算文件哈希、验证数字签名,甚至使用数以千计的数字。
新版本修复了两个错误:
CVE-2021-3711:SM2 解密缓冲区溢出。
CVE-2021-3712:读取缓冲区溢出处理 ASN.1 字符串。
字符串,长短
这些错误中的第二个CVE-2021-3712是两者中危险性较小的一个,具有讽刺意味的是,它与 OpenSSL 处理编码的加密密钥和证书的方式有关。
TLS 密钥和证书文件中的原始数据以一种称为 DER 的格式打包,即Distinguished Encoding Rules 的缩写,它是 ASN.1 的一种形式,Abstract Syntax Notation version 1 的缩写,一种表示二进制数据的结构化方式。
(请注意,如果您曾经查看过 TLS 密钥或证书,您可能已经看到过如下内容:
-----开始公钥----- MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE+LXZfjSOTE0cigDmC3Vlbm0VABgl Zkmp1zbZsiN9ILxqSQy5Krrza94c/eVZORK03gteh9txboKKQOh6LyAftg== -----结束公钥-----
这只是原始 DER 数据的顶部和尾部的 base64 编码版本,与纯二进制文件相比,用于使文件更容易识别并且在传输过程中不太可能被损坏。)
这些名字很长,但重要的不是行话,而是 ASN.1 中文本字符串的存储方式与它们在 Pascal 等编程语言中的存储方式类似,即长度字段后跟那么多数据。
然而,在 C 中,字符串的存储没有任何长度字段:您只需获取原始文本数据,以零 (NUL) 字节结尾。
这使得 C 字符串更易于使用,但由于三个原因,它可能很烦人。
首先,这意味着在遍历整个事物以找出 NUL 字节的位置之前,您永远无法确定字符串的长度;其次,你不能在字符串中间有一个 NUL 字节,即使你想;第三,如果最后一个 NUL 字节被遗漏了,那么复制或打印出一个字符串可能会持续很长时间,并且包含的信息比您预期的要多,假设未终止的字符串后面是一大块非-零数据。
因此,ASN.1 为您提供结构和控制,而 C 为您提供简单性和速度。
为了让您两全其美,OpenSSL 总是在其 ASN.1 字符串中添加一个 NUL 字节,即使这不是必需的。这意味着您可以像往常一样通过 OpenSSL 的特殊 ASN.1 函数访问这些字符串,但也可以直接从 C 安全地读取它们,例如,如果您想打印出包含相关字符串的消息。
实际上(这就是问题所在),这并不完全正确。
您可以安全地将 OpenSSL 的 ASN.1 字符串视为 C 字符串,但前提是它们是由 OpenSSL 的特殊“始终添加 NUL 字节”函数生成的,否则您最终可能会得到一个未终止的字符串,以及所有可能导致的问题。
如果您自己构造了 ASN.1 数据,无论是恶意还是其他方式,您都不需要包含那些讨厌的 NUL 字节,并且直接从 C 使用生成的字符串将不安全——您将需要使用 OpenSSL 的特殊访问功能时间。
不幸的是,一些 OpenSSL 自己的函数被发现走捷径并依赖于从 C 直接访问 ASN.1 字符串,即使他们不能确定原始数据是用那些非常重要的 NUL 字节创建的结束。
因此,通过巧妙的诡计,攻击者可能会欺骗 OpenSSL 打印出超出内存缓冲区末尾的数据。
这种读取缓冲区溢出可能会导致数据泄漏,在这种情况下,私有数据会意外地在日志文件或系统消息等输出中泄露。
或者,读取溢出可能导致内存访问错误,其中 OpenSSL 读取丢失的 NUL 之外的太多额外数据,从而导致发生访问冲突,从而导致软件崩溃。
由于读取溢出而导致的数据泄露正是臭名昭著的 Heartbleed bug 中发生的事情,其中本应发送仅包含内存中几个字节的回复的代码每次都无意中复制到 64 KB。
这会泄露当时内存中相邻的任何其他内容,可能包括恰好在附近的密码或解密密钥。
解密太多
两者中更严重的错误CVE-2021-3711也涉及缓冲区溢出,但这次是写溢出,使其更加危险。
如果您可以在正式分配的内存块的末尾写入并修改控制程序其他部分的数据,那么您将来就可以操纵程序的行为。
例如,您可以诱使它认为某事成功(或失败)而它没有成功,甚至完全接管程序执行流程。
使用诱杀数据来接管正在运行的程序被称为 RCE,远程代码执行的缩写,这正是它所说的意思:其他人,甚至可能在世界的另一端,无需太多弹出对话框或警告。
CVE-2021-3711 漏洞依赖于生成输出数据的软件代码中使用的通用编程习惯用法。
该习惯用法涉及连续两次使用相同的数据输出函数:首先,您运行该函数,但说“不要实际生成数据,只需告诉我真正执行时会有多少”;然后,在留出合适大小的缓冲区后,再次运行该函数以生成实际数据。
这样,理论上,您可以通过确保在开始之前有足够的内存空间来可靠地避免缓冲区溢出。
除了在 OpenSSL 中的一种特定情况下,即使用中国政府的称为上密 (SM)的加密算法时,该软件最终可能会告诉您,您需要的缓冲区大小最多为 62 字节太小了。
这意味着发送到用于解密的诱杀加密数据可能会在 OpenSSL 内部引发严重的、可写的缓冲区溢出。
特别是,如果 OpenSSL 被要求使用上密密码套件建立 TLS 连接,然后在 TLS 握手期间验证另一端提供的 Web 证书,那么看起来似乎有问题的代码最终可能会被调用。
到目前为止,我们还没有发现任何使用此漏洞的有效漏洞。
有点运气
这里的好消息是,尚米的官方 TLS 支持仅在2021 年 3 月的RFC 8998 中引入,因此它是世界加密稳定的新成员。
因此,尽管 OpenSSL 包括 SM 算法的实现(SM2 用于密钥协商和数字签名,SM3 用于散列,SM4 用于块加密)。它还没有包含允许您选择这些算法作为用于 TLS 连接的密码套件所需的代码。就我们所见,您不能要求您的 TLS 客户端代码请求商密连接到其他人的服务器;并且您无法让您的 TLS 服务器代码接受来自其他人客户端的商密连接。
所以错误就在那里,在低级别的 OpenSSLlibcrypto
代码中,但是如果您在 TLS 级别使用 OpenSSL 来建立或接受安全连接,我们认为您无法打开一个会话,其中有错误的代码可能是触发。
我们认为,这大大降低了犯罪分子利用此漏洞在您的笔记本电脑上植入恶意软件的可能性,例如,将您引诱到一个带有诱杀装置的网站,并在连接设置期间向您提供流氓证书。
该怎么办?
如果可以,升级到 OpenSSL 1.1.1l。尽管 Windows、Mac、iOS 和 Android 上的大多数软件不会使用 OpenSSL,因为这些平台有自己的替代 TLS 实现,但某些软件可能包含自己的 OpenSSL 构建,需要独立更新。如有疑问,请咨询您的供应商。大多数 Linux 发行版都有一个系统范围的 OpenSSL 版本,因此请与您的发行版联系以获取更新。(注意:Firefox 不在任何平台上使用 OpenSSL。)
如果您无法升级,请考虑在没有商密支持的情况下重建 OpenSSL。在重建之前将选项传递
nosm2 nosm3 nosm4
给 OpenSSL
config
脚本即可解决问题。鉴于尚无法选择在 TLS 连接中使用尚米米,您应该会发现这是一个无中断的更改。
如果您是一名程序员,请始终假设数据最糟糕。永远不要假设您被要求解构的数据是由您仔细编码到自己的库中的匹配构造函数创建的。制作看起来不像您期望的方式(并且您自己的测试中未涵盖)的诱杀数据包是许多网络安全研究人员的生计。不幸的是,并非所有人都为好人工作。
文章来源by Paul Ducklin
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)