本文分析了2024年8月6日Ronin Network遭受的安全攻击,该事件导致约1200万美元的损失。攻击被白帽黑客实施,漏洞源于Ronin Bridge V2合约中的初始化问题。文章深入探讨了多重签名桥的工作原理、攻击的机制以及如何避免此类攻击,同时也提到事件对用户信任的影响。
Ronin Bridge 是一个用于在以太坊和 Ronin 链之间桥接 ERC20 代币和 NFT(不可替代代币)的应用程序。
Ronin Bridge 是一个多签名桥,意味着多个桥接操作员必须在交易完成之前批准该交易。这种方法确保了跨链交易的高安全性,防止任何单一方恶意操作或进行未经授权的更改。
本节简要介绍了多签名桥及其在 Ronin Network 内的运作。如果你已经对该主题熟悉,可以跳过此部分。
在 Web3 中,多签名(multi-sig)桥是指一种机制,用于在不同区块链网络之间安全地转移资产或数据,需要来自授权参与者的多个密码签名来批准和执行交易。
Ronin-Ethereum 桥促进了 Ronin 与以太坊之间安全可靠的跨链交易,由 22 个桥接操作员管理。每个操作员验证交易的有效性并进行投票,以批准或拒绝交易。为了执行交易,至少 70% 的操作员必须批准,这确保了高安全性和共识。这种彻底的审查过程降低了欺诈或错误转移的风险,并维护桥的完整性。
Ronin 验证者集图示
Ronin Network 在 2024 年 8 月 6 日遭到重大攻击,损失约 1200 万美元。幸运的是,攻击者是一名白帽黑客,归还了被盗资产。此次攻击涉及以太坊主网的两笔交易。
攻击的根本原因是在部署最新的 Ronin Bridge V2 合同时未能正确初始化操作员权重配置。minimumVoteWeight
参数被设置为零,允许任何签名通过跨链验证。
这是该协议遭到的第二次黑客攻击;该协议此前曾在 2022 年 3 月遭到黑客攻击,导致约 6 亿美元被盗。以前的事后分析可以在 此处找到。
在开始漏洞利用之前,非常重要的是关注安全研究员 @0xSimao 发布的以下 推特,他也被称为 0x73696d616f。
一些协议使用巨额客户资金,但并不总是认真对待他们的安全性。因此,白帽黑客受到激励去利用这些协议并归还被盗资产,以获得对他们有价值的时间和精力的补偿。例如,利用该漏洞的白帽黑客获得了来自协议的 5 亿美元悬赏。
这些黑客明白,投入数小时分析协议代码后不获得任何回报的机会是非常高的。
因此,所有协议都必须认真对待其安全问题。
现在,让我们开始漏洞利用分析:
Ronin Bridge 使用可透明升级的代理模式,这是一个智能合约代理模式,允许通过相关的 ProxyAdmin 实例对合约进行升级,确保只有管理员可以升级代理,而其他调用会透明地转发到实现合约。
在 2024 年 8 月 6 日,协调世界时上午 08:48:47,Ronin 团队更新了他们的代理两次,将代理版本从 2 移至 4,并添加了两个单独的初始化函数。
更新交易状态变更
在新实现中,添加了两个单独的初始化函数(initializeV3 和 initializeV4)。
initializeV3 和 initializeV4 函数
问题出在更新交易过程中,仅执行了 initializeV4 函数,跳过了 initializeV3 函数,导致 _totalOperatorWeight 未初始化并默认设为 0。
更新交易调用流程
Ronin Bridge 的早期版本从 MainchainBridgeManager 合约获取总权重,这意味着 _totalOperatorWeight 变量本应重新初始化。然而,由于更新交易中的代理初始化不正确,_totalOperatorWeight 变量未被初始化并等于 0。
_totalOperatorWeight 状态
MEV 机器人在池中找到了此攻击交易,这使得白帽黑客在协调世界时上午 9:37:23 执行了攻击交易,仅在更新后 48 分钟。
让我们分析这两笔攻击交易中第一笔、也是最大的一笔,其中攻击者盗取了约 4000 ETH:
攻击者构造了一个 恶意智能合约,该合约用于调用抽象 Proxy 合约的回退函数,该合约通过 EVM 指令 delegatecall
将所有调用委托给另一个合约。
在这种情况下,攻击者将调用委托给 MainchainGatewayV3 合约,调用 submitWithdrawal 函数,输入如下:
输入数据
submitWithdrawal 函数调用了 _submitWithdrawal 函数,该函数调用了 _computeMinVoteWeight 来提取 minimumWeight 和 locked 变量。
_submitWithdrawal() 函数
Ronin Bridge 的最新升级将总权重存储在合约存储中,变量为 _totalOperatorWeight,当调用 _getTotalWeight 时设置为 _totalWeight。
_getTotalWeight() 和 _computeMinVoteWeight() 函数
这将 _totalWeight 设置为 0,因为 _totalOperatorWeight 未初始化。
_getTotalWeight() 调用返回 _totalWeight = 0
之后,_minimumVoteWeight 被调用,其参数为 _totalWeight,以设置 _weight 变量。然后将此值返回并分配给 _submitWithdrawal 中的 minimumWeight。
_minimumVoteWeight() 调用
由于 _totalWeight
为 0,_minimumVoteWeight 返回 0,从而将 minimumWeight
设置为 0。
_locked
返回 false,使得在 _submitWithdrawal 中的 locked 也为 false。
_computeMinVoteWeight() 返回金额
由于 weight 和 minimumWeight 均为 0,随后的检查成功通过,从而导致 passed 变量被设置为 true。这避免了函数回退,允许调用 handleAssetOut。
handleAssetOut 被调用时,发送了被盗金额 4000 ETH。
handleAssetOut 调用
在 handleAssetOut 中,调用了 send(),将约 4000 ETH 转移至攻击者地址。
handleAssetOut 函数
此次黑客攻击暴露了一个常见的操作问题,即在最新合约升级部署过程中配置错误或参数未初始化。这一疏忽使得 MEV 机器人利用了 minimumVoteWeight
条件,从而使它们能够在无需签名的情况下提取资产。
针对 Ronin Network Bridge 的攻击可通过多种措施进行预防,例如在合约升级期间确保所有关键参数的适当初始化。
此外,该合约在未经过审计的情况下被部署。在将合约部署到主网之前,由第三方专家进行全面的安全审计可以识别潜在的漏洞。此外,严格的测试,包括模糊测试和潜在攻击向量的模拟,也可以帮助发现标准测试过程中可能遗漏的漏洞。
此次攻击的直接后果是损失约 1200 万美元。幸运的是,这次攻陷是由白帽黑客进行的,这意味着所有用户资金将被回收。然而,这一事件无疑影响了用户信任和协议的声誉,因为这是第二次黑客攻击。此外,此类漏洞可能导致市场更广泛的不稳定,特别是如果用户对去中心化金融(DeFi)协议的安全性失去信心。
在攻击发生后约 38 分钟,即协调世界时上午 10:15:23,合约被暂停,并开始调查。一组高度可信的安全专业人士和志愿者 SEAL 911 协助 Ronin 团队进行资金归还的过程。
在攻击几小时后,Ronin Network 团队 宣布 归还了 ETH(约 1000 万美元)并表示他们预计 USDC(约 200 万美元)将在当天晚些时候归还。此外,他们给予白帽黑客的悬赏为 50 万美元,并宣布网络将在重新上线之前进行审计。
- 原文链接: threesigma.xyz/blog/roni...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!