最后,它只是一个简单的字符串比较,比我测试中的实际 HMAC 计算快 2 个数量级。
但这不是恒定的时间。仅仅因为它们完成得很快并不意味着差异是不可测量的。对于bytes
值,Python 首先测试相等的长度和相等的第一个字节,然后再memcmp
用于测试其余部分。对于字符串,Python 比较长度,然后比较种类(如果字符串每个字符使用 1、2 或 4 个字节),然后也使用memcmp
.
Linux 联机帮助页memcmp
明确指出:
不要memcmp()
用于比较安全关键数据,例如加密机密,因为所需的 CPU 时间取决于相等字节数。相反,需要一个在恒定时间内执行比较的函数。一些操作系统提供这样的功能(例如,NetBSD's consttime_memequal()
),但在 POSIX 中没有指定这样的功能。在 Linux 上,可能需要自己实现这样的功能。)
一个足够坚定的攻击者可以利用这个弱点来找出你存储的哈希值与它正在发送的数据的哈希值。
定时攻击使伪造签名成为可能。比如说,服务将授权信息存储在与客户端共享的令牌中。如果客户端可以更改此令牌,则他们可以获得原本无法获得的访问权限。为了防止这种情况,令牌使用 HMAC 签名进行签名,让服务器在接受它为有效之前验证返回的令牌。如果授权数据与签名不匹配,则拒绝令牌。
如果服务器这样做:
auth_data, signature = split_token(token)
expected = hmac_signature(auth_data)
if signature == expected:
# ...
然后攻击者可以检测到伪造签名的多少字符与预期的签名匹配,并进行相应的调整。它们以 开头XXXXX:000000...
,然后 tryXXXXX:1000000...
等,直到服务花费的时间增加,表明它们具有匹配的第一个字符。然后可以更改第二个字符,直到完整的签名匹配。