签名计数器
如果在WebAuthn中查看已签名消息的结构,你会注意到其中一个字段被称为"签名计数器"。在之前的长文中我曾建议忽略它——这个建议仍然正确——但以下是具体原因。
签名计数器对认证器来说是可选的实现功能:安全密钥没有签名计数器也是有效的,尽管绝大多数确实具备。在这种情况下,计数器值始终为零。但一旦网站看到非零值,安全密钥就必须确保对于给定凭证的所有未来声明,计数器值严格递增。
签名计数器的动机在于它可能帮助网站检测安全密钥是否被克隆。克隆安全密钥本应非常困难:至少需要物理接触设备,理想情况下还需要花费大量时间进行侵入式探查。但如果假设所有这些都已发生,攻击者就能克隆安全密钥(可能在此过程中破坏原设备),提取凭证的私钥,并制作一个可工作的复制品——这个复制品可被悄悄放回合法用户手中,使其毫无察觉。此时,攻击者就能随意创建声明,因为他们掌握了凭证的私钥。
如果所有这些确实发生,签名计数器可能会暴露问题。除非攻击者能准确知道合法用户何时创建声明并增加计数器,否则最终他们或真实用户总会创建计数器未递增的声明。
虽然你可能已经看出,但我认为这是一个相当牵强的场景。不过,如果网站想要使用签名计数器,就必须将任何非递增的计数器视为锁定账户并触发调查的信号。至少,相关安全密钥应该被更换。单纯拒绝声明毫无意义:攻击者只需增加计数器重试,而普通用户会以为这是临时故障并做同样操作。
然而,在我见过检查签名计数器的网站中,它们总是将其视为瞬时错误。我从未听说签名计数器真正用于捕获攻击。
另一方面,许多安全密钥只有一个全局签名计数器,这使得不同网站可以关联同一安全密钥的使用情况。也就是说,你安全密钥的当前计数器值具有一定标识性,并可与你使用频率的信息结合。因此,一些安全密钥实现了更细粒度的签名计数器——这值得称赞,但我认为这相当浪费。
当通行密钥在设备间同步时,它们从不实现签名计数器,因为这要求设备组维护一致的值。因此,随着时间的推移,你可能会观察到大多数凭证都没有签名计数器。