Vyper 被黑的时间线和反思
“Trust but verify”(信任,但要核查),不要做“事后诸葛亮”。最厉害的 bug 都是灯下黑。
由于合约的不可变性, 项目会隐性依赖多年前编写的代码, 我们在修复 bug 时,就更需要注意它的潜在影响。
这次的事情是这样发生的。
时间线
在本文中,我会用“我们”来指代所有为这次事件努力的人。我觉得,虽然我最初对发现漏洞作出了一些贡献,但在整个过程中,有无数人提供了更多的帮助。
13:10 UTC pETH/ETH 1100 万美元[1] 流失。
13:19 UTC Michal 在 ETHSecurity 上发布有关 pETH 价格突然暴跌的消息。
Igor 首先注意到不对劲。多亏了他,我们开始深入调查。
但是机器人是如何在
remove_liquidity()
调用中重入add_liquidity()
的呢?
14:01 UTC 就这个问题组建了一个应急小组。
14:07 UTC 我们用我们最喜欢的反编译器[2]反编译了 JPEGd 合约,并注意到重入保护存储槽有点不同。
// Dispatch table entry for add_liquidity(uint256[2],uint256)label_0057: if (storage[0x00]) { revert(memory[0x00:0x00]); } storage[0x00] = 0x01;// Dispatch table entry for remove_liquidity(uint256,uint256[2])label_1AF3: if (storage[0x02]) { revert(memory[0x00:0x00]); } storage[0x02] = 0x01;
14:27 UTC 我们通过一个简单的本地测试合约确认了这个问题。
@external@nonreentrant("lock")def test(addr: address) -> bool: return True@external@nonreentrant("lock")def test2(addr: address) -> bool: return False
这不仅仅是另一个重入 bug。
此时,我们意识到这将产生多大的影响。封锁消息,我们删除了有关该漏洞的公开消息。
14:37 UTC Wavey 帮助确认了存在漏洞的提交和受影响的版本。我和 Charles 通过手动检查 Vyper 编译器输出也证实了这一点。
这是一场与黑客的竞赛。
值得庆幸的是,人们还将其与只读重入混淆。摘自 “Web3 安全警报” 频道-Alchemix 和 Metronome DAO 也因只读重入 bug 遭到黑客攻击[3]
Michael 发现运行 0.2.15 版本的 alETH 和 msETH 池也存在潜在漏洞。
14:50 UTC msETH/ETH 被耗尽[4]。
15:34 UTC alETH/ETH 被耗尽[5]。
15:43 UTC 我们发现用 Vyper 版本 0.3.0 编译的CRV/ETH 存在漏洞[6]。我们必须尽可能长时间保密受影响的合约,这一点至关重要。
16:11 UTC 我们开始研究白帽漏洞。
不幸的是,太多的组织在同时进行独立研究,谣言四起。16:44 UTC,我们决定针对受影响的版本发布公开声明[7]。
到 18:32 UTC,我们有了一个可用于潜在白帽拯救的概念证明漏洞。Chainlight 的 bpak 也同时在研究一个漏洞,并于 19:06 UTC 分享。
五分钟后,19:11 UTC,有人盗走了资金[8]。
攻击结构与我们的概念证明有很大不同,不太可能是我们团队泄密。无论如何,这非常令人沮丧。
尽管如此,还有很多事情要做。
21:26 UTC Addison 提出了一个雄心勃勃的计划,拯救 CRVETH 池中的剩余资产。
如果你将 30k crv 发送到 crv/eth 池,
你可以更新管理费(admin fee) 然后设置 crv/eth 费率约为每个 crv 0.15 eth
基本上可以全部提取走池中的数百 K crv
21:52 UTC bpak 做了一个可行的概念证明,可以拯救 3100 ETH。
十分钟后,22:02 UTC,我们再次被击败。出乎意料的是,CRV 管理费用机器人[9]已被取走资金,并且池子已耗尽[10]。
责备
责备(Balme) 是一个很强烈的词。指责是没有用的。我认为思考一下哪些方面可以做得更好才是有用的。
竞赛
白帽的努力都在不到半小时的时间内被击败。有时候,每一秒都非常重要。
也许可以有更好的准备和资源来执行这些攻击。同时,这似乎是一把双刃剑。把如何执行黑客攻击的信息汇总起来真的是个好主意吗?我们应该信任谁?
另一方面,我认为整个过程非常有效。我们在 2 小时 4 分钟内从最初的怀疑到确认出谁易受攻击。
信息泄露
我既是审计员又是白帽黑客。
审计行业有着特有的发布文化。我们因技术思想领先和对漏洞的深刻理解而获得报酬。证明他们的领先与深刻的一种方法是发布[11]有关黑客行为的“独家新闻”。研究人员花费巨大,而投资的回报就是宣传。
另一方面,有一个令人信服的论点认为:受影响版本的早期披露会对白帽拯救产生重大影响。
如果再多半小时,就可以拯救 1800 万美元。
审计师不会为他们的报告所造成的影响付出代价。相反,他们会得到点赞、转发和报道。这似乎是一个问题。
下一步
我不同意“我们需要形式化验证来解决这个问题”之类的观点。这个错误可以通过单元测试来捕获。形式化验证对于许多错误类型都非常有用,但我不相信它对于相对简单的、未优化编译器也同样有用。
需要注意的是,这个错误在 2021 年 11 月已修复[12]。
我认为这个 Vyper 漏洞不是 Vyper 团队的技术或语言本身的问题,更多是流程问题。这个错误在很久以前的版本已被修复,但在修复的时候并没有意识到它的潜在影响。
不幸的是,公共物品很容易被忽略。由于合约不可变性,项目会隐性依赖多年前编写的代码。协议开发人员和安全专家应该了解整个执行堆栈的最新安全开发情况。