2

在某些库中,例如flask-bcrypt,如果两个字符串的长度不同,我们可以看到代码提前退出:

def constant_time_compare(val1, val2):
    '''Returns True if the two strings are equal, False otherwise.

    The time taken is independent of the number of characters that match.
    '''

    if len(val1) != len(val2):
        return False

    result = 0
    for x, y in zip(val1, val2):
        result |= ord(x) ^ ord(y)

    return result == 0

这真的安全吗?这肯定会向攻击者揭示这两个字符串早期的长度不同并泄露了信息?

4

1 回答 1

4

在防止定时攻击时,以不同的长度退出是否安全?

一般不会,但要视情况而定。

函数本身

无论长度比较如何,此函数都会通过定时攻击泄漏信息,因为它的运行时间始终取决于其输入的长度。

通过长度比较,当两个输入的长度相同时,运行时间会发生变化。

如果没有长度比较,运行时间将根据较短输入的长度而变化(因为zip)。一旦攻击者控制的输入超过另一个输入的长度,运行时间将保持不变。

虽然这个函数的运行时间很短(不科学的测试表明 32 字节的输入不到 0.1 毫秒),但在现实生活中,由于其他因素,攻击者很难利用它,例如网络延迟的变化。攻击者可能需要已经在执行代码的机器上才能真正利用这个弱点。

关于烧瓶 bcrypt

但是,在 flask-bcrypt 的上下文中,此函数仅用于比较哈希,而不是直接用户输入。因为 bcrypt 输出的哈希长度是固定的,所以return False不应该实际执行。因此,当与 bcrypt 一起使用时,此函数不存在时间攻击。

Flask-bcrypt 使用此函数来检查相等性,因为 python (==) 中正常字符串比较的运行时间将根据字符串的内容而变化。考虑两个长度相同的几乎相同的字符串,如果两个字符串的第一个字符不同,== 比较将比在字符串的最后一个字符出现差异时更快完成。

我会争辩说,在这种情况下,恒定时间字符串比较确实是不必要的。攻击者的目标是根据处理时间推断存储的哈希值,攻击者需要知道他们的输入产生了什么哈希值来实现这一点。知道正在产生什么哈希的唯一方法是让攻击者知道工作因子和盐,如果他们有这些信息,那么他们也已经有了哈希(因为它们都存储在一起)。在这种情况下,没有理由一开始就执行攻击。

于 2013-08-29T12:45:34.513 回答