翻转比特的踪迹:AES-GCM在可信执行环境中的加密漏洞剖析

本文深入分析可信执行环境中AES-GCM加密算法的安全漏洞,探讨如何通过Forbidden攻击翻转私钥分片比特,逐步恢复ECDSA私钥,并揭示Shamir秘密共享算法在此场景下的潜在风险。

翻转比特的踪迹 - The Trail of Bits博客

可信执行环境(TEE),如安全飞地(secure enclaves),正日益普及用于保护云中的资产。它们的承诺很诱人,因为当飞地被正确使用时,即使是飞地的操作员或云服务提供商也不应能够访问这些资产。然而,这导致了一个强大的攻击者模型,其中与飞地交互的实体可能就是攻击者。在这篇博客文章中,我们将探讨一种涉及AES-GCM、ECDSA和Shamir秘密共享算法的密码学在此设置中可能失败的方式——具体来说,通过使用对AES-GCM的Forbidden攻击来翻转私钥分片上的比特,我们可以迭代地恢复私钥。

可信飞地

TEE有各种形状和大小。它们可以使用单独的安全硬件实现,例如硬件安全模块(HSM)、可信平台模块(TPM)或其他专用安全芯片作为片上系统(SoC)的一部分。也可以在使用内存隔离技术(如TrustZone或虚拟机监控程序)与不可信实体共享的硬件中实现它们。此类别的例子包括Intel SGX、Amazon Nitro等安全飞地。

安全飞地面临的一个挑战是它们几乎没有持久内存,因此需要在电源周期之间可用的大量数据必须存储在飞地外部。为了保持这些数据的安全,必须使用存储密钥进行加密,该密钥要么存储在可信环境内部,要么存储在限制对飞地访问的外部密钥管理服务(KMS)中(例如,通过某种形式的认证)。

图1:典型安全飞地的设计,其中加密数据存储在飞地外部,数据加密密钥安全地存储在飞地外部的KMS中

然而,由于数据存储在外部,与飞地交互的不可信实体将看到这些数据并可能修改它。即使使用强密码学,如认证加密——通常是带有关联数据的认证加密(AEAD)——飞地也很难保护自己免受回滚攻击,其中不可信实体用同一数据的早期版本替换外部数据,因为两者都会通过认证。一个诱人的解决方案是对存储在飞地外部的数据进行版本控制,但由于飞地是无状态的,不知道最新版本应该是什么,这很快变成了一个鸡生蛋蛋生鸡的问题。因此,在此设置中跟踪版本号或使用计数器是困难的,如果不是不可能的话。

在可信飞地中签名

可信飞地的一个有趣应用是持有数字签名私钥(如ECDSA密钥)以执行签名。如果设置正确,没有人可以从飞地中泄露签名密钥。然而,由于签名密钥必须在飞地电源周期后仍然可用,它们通常必须持久存储在某个外部存储中。为了防止任何有权访问此外部存储的人获取或修改签名密钥,需要使用AEAD对其进行加密。

图2:使用可信飞地进行签名的设计,其中加密的签名密钥存储在飞地外部,并使用由KMS保护和管理密钥进行加密

进入每个人最喜欢的AEAD:AES-GCM!由于其脆弱的设计,一旦nonce被重复用于加密两个不同的签名密钥,认证保证就不可逆转地被破坏。由于AES块大小限制为128位,并且需要32位用于计数器,你只有96位用于nonce。不过不用担心;你只需要确保不要使用随机nonce调用AES-GCM超过2^32次!所以飞地只需要跟踪一个使用计数器。唉,如前所述,这基本上是不可能的。¹

图3:在飞地中防止AES-GCM滥用需要维护状态以监控AES-GCM使用,并且必须防止攻击者重放旧状态的滚回攻击,尽管这在实践中难以实现。

因此,攻击者可以让飞地生成任意数量的签名密钥,所有这些都必须加密以存储在外部。最终,nonce将重复,攻击者可以使用Forbidden攻击恢复AES-GCM哈希密钥。细节不是很重要,但本质上,有了AES-GCM哈希密钥,攻击者可以获取任何现有的AES-GCM密文和标签,以某种方式修改密文,并使用哈希密钥更新标签。具体来说,他们可以翻转密文中的比特,当飞地解密时,将导致原始明文,除了相同的比特被翻转。这不好。但有多糟糕?

攻击ECDSA签名

该攻击并非特定于ECDSA,因此不需要理解ECDSA背后的所有具体数学。理解攻击所需的唯一重要背景是理解ECDSA密钥对是如何构建的。私钥对应一个数字(也称为标量)d。要获得相应的公钥Q,私钥乘以你想要使用的特定椭圆曲线的基点G。

Q = d · G

通过利用被破坏的AES-GCM认证,攻击者可以翻转加密私钥中的比特,并让飞地解密并使用它来签名消息。由于AES-GCM的加密部分本质上是计数器模式,翻转加密私钥中的比特将导致相应明文私钥中的相同比特翻转。

图4:通过修改存储在外部存储中的密文,攻击可以使安全飞地使用修改后的密钥签名消息,而无需针对飞地本身。

当我们翻转私钥的最低有效位时会发生什么?零比特会变成一,这相当于给私钥加一。相反,一个一会变成零,这相当于从私钥中减去一。本质上,比特翻转对私钥的影响取决于私钥比特的未知值。

这很好,但如果我们不知道私钥,我们怎么知道这两种情况中发生了哪一种?好吧,如果我们用翻转的私钥生成签名,我们可以通过添加或减去生成器来使用修改后的公钥验证签名。如果它用添加的生成器验证,我们知道私钥比特是零,而如果它用减去的生成器验证,我们知道私钥比特是一。

(d + 1) · G = d · G + G = Q + G
(d – 1) · G = d · G – G = Q – G

我们现在可以重复这个过程来恢复私钥的其他比特。我们将不是加或减一,而是加或减私钥的二次幂。通过从公钥加或减生成器的相应倍数,我们了解私钥的一个新比特。严格来说,一次恢复一个比特不是必需的。你可以翻转多个比特,并基于这些翻转比特对私钥的所有可能影响尝试签名验证。

分割比特

有趣的是,当私钥在加密前使用Shamir的秘密共享算法分割成不同的分片时,攻击仍然有效。飞地接收不同的加密分片,解密它们,将分片重新组合成私钥,然后签名。结果,我们不能直接翻转私钥中的单个比特。

但当我们翻转其中一个分片中的一个比特时会发生什么?在Shamir的秘密共享中(另见我们关于此主题的优秀ZKDocs文章),每个分片由一对x和y值组成,用于使用拉格朗日插值插值一个多项式。秘密值由在x = 0处评估的插值多项式的值给出。

翻转其中一个y值中的比特会改变插值多项式,这对应于一个不同的秘密——在我们的例子中,是私钥。基本上,重新组合秘密对应于加权y值的总和,其中每个权重是一个拉格朗日系数λj,可以很容易地从x坐标计算(通常选择为从一到分片数量的连续整数)。

将所有这一切放在一起,翻转其中一个份额中的比特会根据比特的值给份额加或减。这然后导致从私钥加或减相应拉格朗日系数λj的倍数。通过用这个修改的私钥生成签名并使用修改的公钥验证它们,我们可以逐位恢复秘密份额的值。在获得份额后,我们可以将它们重新组合成私钥。总而言之,这表明飞地操作员可以从飞地中提取私钥,尽管涉及所有密码学和隔离。

最后一点

正如对安全飞地中AES-GCM的Forbidden攻击的探索所揭示的,密码学原语如AES-GCM、ECDSA和Shamir的秘密共享,虽然通常稳健,但如果部署不正确,可能仍然容易受到攻击。TEE的复杂性和对抗方法的不断演变使得保护敏感数据成为一项困难的任务。在Trail of Bits,我们理解这些挑战。利用我们在密码学和应用程序安全方面的深厚专业知识,我们提供全面的系统审计,识别潜在漏洞并提供有效的缓解策略。通过与我们合作,开发人员可以更好地避免潜在的密码学陷阱并提高其TEE的整体安全状况。

¹ 你可能会争辩说,在这个玩具示例中,KMS可以跟踪使用计数器,因为它控制对存储密钥的访问。然而,在实践中,KMS通常在它可以加密和解密的数据类型上相当有限(通常只有密码学密钥)。例如,可能无法加密秘密密钥分片。

如果你喜欢这篇文章,分享它:
Twitter
LinkedIn
GitHub
Mastodon
Hacker News

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计