为什么不应该使用 memcmp 来比较安全关键数据?

信息安全 定时攻击 时间
2021-08-26 19:15:19

来自man 3 memcmp

不要 memcmp()用于比较安全关键数据,例如加密机密,因为所需的 CPU 时间取决于相等字节数。相反,需要一个在恒定时间内执行比较的函数。

为什么呢?我的想法是,如果有人可以访问处理这些“安全关键数据”的机器,那么这些秘密已经被泄露,因为那个人可以从 RAM 中提取它们。或者,如果那个人无法访问机器,那么他们无论如何都无法准确测量 CPU 时间。

3个回答

利用时间信息是对密码认证系统之类的一种可能的攻击。

从概念上讲memcmp(),通过逐字节比较两组二进制数据来工作(实际上处理器可以一次比较多个字节,具体取决于优化,但以下相同的原则将适用)。该函数从数据的开头开始,依次比较每个字节,一旦发现差异就退出。如果没有发现差异,则该函数返回一个代码,表明数据匹配。

由于该函数一发现差异就返回,因此具有足够准确时钟的攻击者可以推断出秘密信息。他们可以memcmp()用不同的输入诱导调用,并通过测量哪些输入需要更长的时间,他们可以推断出存储的秘密可能是什么。

例子:

考虑一个经典的密码散列系统。假设您的密码存储为秘密哈希,例如Ek8fAMjPhBo. (该哈希是使用 Linux 函数提供的 DES 方案生成的crypt(),盐为na,密码为secret。请注意,此函数不安全,您不应在实际系统中使用它。)

在强密码系统中,您的哈希Ek8fAMjPhBo被存储,但您的密码被存储。当您被要求进行身份验证时,系统将获取您的密码,对其进行哈希处理,然后将两个哈希值相互比较。如果生成的散列匹配,则授予您访问系统的权限,如果散列不匹配,则拒绝您的密码。这允许系统检查您是否知道您的密码,而无需实际存储密码本身。

攻击者如何利用时间来攻击这个系统:

为了攻击这个系统,对手真的只需要弄清楚什么密码散列到存储的散列中。通常存储的散列是保密的,但攻击者可以使用时间信息来推断存储的散列可能是什么。一旦对手推断出存储的哈希值,它就很容易受到更快的离线彩虹表攻击,以及绕过密码重试限制等在线安全措施。

上面的密码系统必须将候选哈希与存储的哈希进行比较才能正常运行。假设将候选散列的每个字节与秘密存储的散列进行比较需要 10 纳秒。如果没有字节匹配(一次比较),则memcmp()大约需要 10ns。如果一个字节匹配(两次比较),那么memcmp()大约需要 20ns。您的攻击者会生成一些密码并在系统中运行它们,并记录每个密码需要多长时间。假设前几次散列比较每次大约需要 10ns 然后返回,表明候选散列的所有字节都与存储的散列不匹配。经过几次尝试后,其中一个哈希比较需要 20ns,这表明候选哈希的第一个字节与存储的哈希匹配。在上面的例子中,这表明攻击者已经推断出哈希的第一个字节Ek8fAMjPhBoE.

设计的哈希具有您无法预测哪个哈希将对应于哪个密码的属性,因此例如这不会告诉攻击者密码以s. 然而,攻击者可能有一个预先计算好的哈希表(彩虹表),因此他们可以查找其他以 . 开头的字符串哈希的密码E在他们尝试了足够的哈希之后,他们最终会得到一个memcmp()需要 30ns 的输入,这表明前两个字节匹配,并且他们推断出哈希的前两个字节是Ek. 他们一遍又一遍地重复这个过程,直到他们推断出所有或大部分哈希。那时他们要么知道密码,要么可以通过传统的彩虹表攻击暴力破解密码。

这有点假设,但您可以在网络上的其他地方找到许多有关定时攻击的实用信息,例如:

https://research.kudelskisecurity.com/2013/12/13/timing-attacks-part-1/

问题并不是真的要争辩说旁信道攻击在您为系统考虑的任何应用程序中都是可行

一个更好的观点是

  1. 在大多数开发人员临时想不到的情况下,可能会发生侧信道攻击。

  2. 在任何给定的情况下,可靠地说服自己没有机会进行定时攻击在开发时比简单地使用安全比较方法作为 SOP要做的工作要多得多。更多的工作意味着更多的成本和更高的出错风险。

简而言之,它是唾手可得的果实。我能想象到的几乎所有参数上,制定“从不使用memcmp安全关键数据”的政策都优于“memcmp安全时可以使用”的政策


如果您遇到的情况是,在每次不匹配的比较中节省几分之一微秒的 CPU 时间(这通常首先是不常见的情况!)将为您节省足够的钱,值得花费精力如果进行适当的安全分析,那么您将有大量的商业文件证明这一事实。

(即便如此,在让摩尔定律为您完成工作的同时,仅阅读漫画会花费您进行分析的时间,可能会同样为您节省那些 CPU 微秒)。

它属于侧信道攻击的类别(与 RSA 的要求相同,使用私钥的执行时间应该是恒定的)。此外,RAM 不一定会受到损害,操作可以在 TEE(可信执行环境)上执行。