在某些库中,例如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
这真的很安全吗?当然,这向攻击者揭示了这两个字符串早期的长度不同并泄露了信息?
答案 0 :(得分:3)
在防止定时攻击时,退出不同长度是否安全?
一般不会,但它确实取决于具体情况。
功能本身
无论长度比较如何,此函数都会使定时攻击泄漏信息,因为它的运行时间总是取决于它的输入长度。
通过长度比较,当两个输入长度相同时,运行时间将会改变。
如果没有长度比较,运行时间将根据较短输入的长度而变化(因为zip
)。一旦攻击者控制的输入超过了另一个输入的长度,运行时间将保持不变。
这个函数的运行时间很短(不科学的测试显示32字节输入小于0.1ms),在现实生活中,攻击者很难利用这个功能。网络延迟变化等因素。攻击者可能需要已经在执行代码的机器上才能真正利用这个弱点。
关于flask-bcrypt
在flask-bcrypt的上下文中,此函数仅用于比较哈希值,而不是用于直接用户输入。因为bcrypt输出的哈希长度是固定的,所以return False
永远不会实际执行。因此,当与bcrypt一起使用时,此功能不存在时间攻击。
Flask-bcrypt使用此函数来检查相等性,因为python(==)中正常字符串比较的运行时间将根据字符串的内容而改变。考虑两个相同长度的几乎相同的字符串,如果两个字符串的第一个字符不同,==比较将比字符串的最后一个字符出现差异更快地完成。
我认为,虽然在这种情况下,常量字符串比较实际上是不必要的。攻击者的目标是根据处理时间推断出存储的哈希值,攻击者需要知道他们的输入产生了什么哈希值才能实现这一点。知道正在生成什么哈希的唯一方法是攻击者知道工作因素和盐,如果他们有这些信息,那么他们也已经有了哈希(因为它们都存储在一起)。在这种情况下,没有理由开始执行攻击。