文章讲述了ERC1271标准中签名重放漏洞的发现与解决过程。作者发现,如果智能合约签名的摘要不包含智能合约账户地址,则可能在同一所有者的多个账户之间重放签名。文章讨论了钱包和外部应用程序在此问题中的责任,并列出了受影响的钱包以及修复方案,并强调了EIP参考实现的安全问题和签名使用的注意事项。
ERC1271 重放 - 超过15个团队受到影响
curiousapple
第一章 - 导火索
第二章 - 讨论:谁负责,钱包还是外部应用?
第三章 - 搜索和报告
第四章 - 修复、经验教训、致谢和赏金
9月25日:我当时在研究 Cowswap,发现他们的订单结构中不包含用户地址,这与其他大多数基于意图的项目(如 Uniswap X)不同。
进一步思考,我意识到如果这些账户有共同的所有者,这可能导致智能合约签名在多个账户之间被重放。
如果你不熟悉,智能合约签名是通过 ERC1271 实现的,其中调用者调用智能合约,智能合约检查给定的摘要是否由其中一个所有者签名。
ERC-1271: 合约的标准签名验证方法 \ 当账户是智能合约时,验证签名的标准方法 \ eips.ethereum.org
来自 EIP 的参考实现
function isValidSignature(
bytes32 _hash,
bytes calldata _signature
) external override view returns (bytes4) {
// 验证签名
if (recoverSigner(_hash, _signature) == owner) {
return 0x1626ba7e;
} else {
return 0xffffffff;
}
}
现在,如果给定的签名摘要 ( _hash
) 独立于智能合约账户呢?
所有者为 A 的智能账户签名的智能合约签名,是否可以在 A 拥有的任何其他智能账户上重放?更广泛地说,EOA A 签名的签名是否可以在 A 拥有的智能账户上重放?
事实证明答案是YES,如果签名摘要不包含智能账户地址。这就是问题的关键。
你可以在这里找到给 Cow 的初始报告 https://gist.github.com/0xcuriousapple/f68f63ab25f463f8f9fb5759209ab497
由于他们没有将签名者(用户地址)包含在订单结构中,因此也没有包含在签名摘要中,因此 CowSwap 的订单可能会在具有相同所有者的智能合约账户上重放。对于 Cow 来说,情况更严重,因为他们的 nonce 处理方式是独一无二的。基本上,他们根据订单哈希将订单标记为已完成或未完成。因此,为了使这种情况发生在 Cow 上,你甚至不需要 nonce 同步。
Cow 团队在整个报告过程中都很勤奋,并承认了它的存在。他们保证他们将自己监控此类订单,并开始将用户地址作为额外的参数进行哈希处理。
请注意,并非所有钱包都容易受到这种攻击。
有些钱包,如 Safe 或 Sequence,会自行哈希账户地址,从而消除这种攻击媒介。
因此,Cow 团队也指出,理想情况下,钱包应该像 SAFE 一样处理这个问题。
图片来源于 Nick McDonell 的 The Council of Animals
最初,我认为这是一个与 Cowswap 相关的问题,所以我只向他们提出了这个问题。但钱包应该理想地处理这个问题的观点越来越受欢迎。
在我可以索引的所有钱包中,只有 Safe、Sequence 和 BlocTo 是非易受攻击的。
我还发现,还有其他协议如 CowSwap 希望钱包处理这种情况。 例如,Uniswap 的 Permit 2、Arcade、Lens 和 ETH Attestation。
因此,现在我不确定这到底是谁的责任? 钱包还是外部应用程序?
Cow 团队与 Safe 团队进行了对话, Safe 团队指出,理想情况下,钱包应该处理这个问题,而不应该依赖 ERC1271 的示例实现。
我咨询了一些其他相关方,包括 ERC4337 的作者、其他应用程序开发人员和 Francisco Giordano ( @frangio) (ERC1271 的作者之一)。
对于谁负责,意见不一,但最终,大多数人一致认为钱包应该处理这个问题。
钱包问题的 主要论点是,从外部应用程序的角度来看,这种情况区分了智能账户和 EOA。
外部应用程序应该采取措施来防止一般情况下的签名重放,例如 chain.id
。 但是,在智能账户的共同所有者的情况下,理想情况下应该在源头(即钱包代码中)阻止它,因为它特定于它们。
Frangio 还承担了在官方 EIP 本身中进行必要修改的任务,并且一直在那里领导对话🫡
然而,已经过去了将近 3 个月,由于多种观点,它一直滞后。 EIP 参考实现中的问题引发了关于 EIP 安全披露的更广泛讨论,但尚未解决。 你可以在这里关注它的进展
接下来,我决定将其报告给所有受影响的钱包
现在是结局的时候了:找到所有受影响的钱包并向其报告。 我使用了我能使用的所有工具:
Alchemy 的钱包列表
GitHub
Codeslaw
TinTin 的避难所
几天来,我的日常安排是搜索 isValidSignature
实现,确定它是否受到影响,查找联系信息,为每个团队编写自定义的问题报告并进行报告。
个人抱怨:纯粹的痛苦,完全是由于这个问题本身的性质。 多个团队受到影响,而且没有简单的方法一次性联系到他们。 这是一个被广泛采用的实现,在直接搜索中有成千上万个实例。 因此,你必须在搜索中具有创造性和持久性。 此外,找到一个易受攻击的实现仅仅是开始;找到联系信息并建立沟通是一个更大的问题。
与此同时,Alchemy 的工程师 Howy 也在 10 月 27 日左右自行发现了 LightAccount 上的这个问题,并首先报告给了 Uniswap,因为它被更广泛地使用。你可以在这里找到他的 Permit 2 的概念验证:https://github.com/omgwiNNING/replay-sig-poc
他创建了一个 Telegram 群组,并添加了 Uniswap 团队和受影响的钱包。 由于我与受影响的钱包保持联系,我也加入了该群组。 从那时起,钱包社区及其成员一直在那里进行讨论。
该群组现在非常不活跃,但如果你想加入,请联系我或 Howy。
当一切尘埃落定时,以下是接受该问题的钱包。
Ambire
ZeroDev
Biconomy (从 V2 开始解决,但仍存在于 V1 中)
Soul Wallet
Etherspot
Openfort
Thirdweb
Unipass
Instadapp
Enso
OKX
Light Account (Alchemy)
Hats Wallet
Fuse
Solady
Ambire 的报告供参考:Ambire's Report
如果我没记错的话,上述列表中还有一些其他的钱包,大约5-6个。 一些放弃了这个问题,一些从未回应,而另一些则澄清了为什么这个问题不会影响他们,例如 Argent。 即使 Argent 使用相同的参考实现,这也不适用于它们,因为在它们的情况下,账户的签名者不能单独用作 EOA。 它是在设备上生成的,并且不向用户公开。
可以通过在签名摘要中添加账户地址来解决此问题。 你可以参考 Safe 的实现来找到解决方案。
但是,在像 Safe 这样的直接实现中,你会发现它会导致用户的不透明签名。
因此,我们(Ivo,Frangio,Vectorised)一直在讨论以一种不会导致用户不透明签名的方式来解决它(以便他们可以在其硬件钱包上验证它们)。
Frangio 和 Vectorised 都在他们的 github 上提出了他们的解决方案。
请注意,截至目前,以上均未经过审计,仅供参考。
目前,你不应依赖和复制参考 EIP 实现,因为它们只是为参考而提供,并且尚未经过审计。
关于签名: 对签名保持警惕。 它们可能很棘手,并且始终会保持棘手,仅仅是因为有人能够代表你执行它们。 任何泄露都会让你完蛋。
请务必在已部署的合约源代码中包含你的安全联系信息。 这将使任何人都可以更轻松地与你联系。
Frangio (ERC1271 的合著者),@frangio_
Ivo (Ambire), @Ivshti
Felix (Cow), @fleupold
Taek (Zerodev), @leekt216
Vectorised (Solady), @optimizoor
Howy (Alchemy), @howydev
还有很多其他人
Ambire (Immunefi)
Instadapp (Immunefi)
Biconomy (自己的)
Cow (Immunefi)
谢谢,
图片来源于 @comedywildlifephoto
- 原文链接: mirror.xyz/curiousapple....
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!