2023年4月3日,以太坊上的多个MEV机器人在16964664区块中遭到攻击,一名恶意验证者替换了8个交易,导致5个MEV机器人损失约2538万美元。攻击主要针对与Flashbots相关的MEV机器人。漏洞在于Flashbots的mev_boost_relay
模块未正确处理错误,恶意验证者利用这一点修改区块内容并成功使其被主网接受,最终攻击者耗尽了MEV机器人的资金池。
2023 年 4 月 3 日,多个 MEV 机器人被黑客在以太坊的 16964664 区块中利用。一个恶意的验证者替换了 8 笔交易,导致 5 个 MEV 机器人总共损失了约 2538 万美元。调查显示,此次攻击主要针对与 Flashbots 相关的 MEV 机器人。
遭受损失的 MEV 机器人
0x00000000008C4FB1c916E0C88fd4cc402D935e7D // 4 txs
0x00000000008C4FB1c916E0C88fd4cc402D935e7D
0x000000000035B5e5ad9019092C665357240f594e
0x00000000003b3cc22aF3aE1EAc0440BcEe416B40
0xE8c060F8052E07423f71D445277c61AC5138A2e5
MEV 机器人不断跟踪 mempool 中用户的交易,以寻找套利机会。他们经常执行所谓的“三明治攻击”,即在用户交易之前和之后都进行一笔交易,本质上是将用户的交易“夹”在中间。例如,当 MEV 机器人检测到用户想要用 A 购买 B 时,它会抢先发送一笔交易,用 A 购买 B,从而抬高 B 的价格,使用户以更高的价格购买 B。在用户购买之后,B 的价格将被推得更高,然后 MEV 机器人将发送另一笔交易,将 B 出售为 A。MEV 机器人通过这种“三明治”操作从差价中获利。当然,MEV 机器人还有其他的盈利方式,我们现在忽略不计。
此事件的关键问题是,一个恶意的验证者替换了原始的交易内容。这导致本可以通过三明治交易对他人进行套利的 MEV 机器人,成为了套利的目标。此外,恶意验证者成功地使修改后的区块被主网接受。
通常情况下,验证者无法修改区块内容并使其被主网接受,原因如下:
恶意的验证者是如何设法让修改后的区块被主网接受的?
事实上,恶意的验证者有信心他们可以胜过 relayer。他们利用了 Flashbots 的 mev_boost_relay
模块中的一个漏洞,该模块没有正确处理错误情况。当一个区块无效时,广播会失败,但 mev_boost_relay
仍然会返回区块的内容。这使得 validator 可以访问区块内容并对其进行修改。并且由于之前的区块广播失败,修改后的区块无需竞争即可被主网接受。
让我们看看 validator 第一次提交的区块的内容。
来自 https://twitter.com/samczsun/status/1642848556590723075
该区块的 parent_root
和 state_root
均为 0,表明该区块无效。Relayer 将其广播到主网,但它很快被拒绝。但是,relayer 仍然返回了区块的内容,从而为恶意的 validator 提供了可乘之机。
// Publish the signed beacon block via beacon-node
go func() {
if api.ffDisableBlockPublishing {
log.Info("publishing the block is disabled")
return
}
signedBeaconBlock := SignedBlindedBeaconBlockToBeaconBlock(payload, getPayloadResp)
_, _ = api.beaconClient.PublishBlock(signedBeaconBlock) // errors are logged inside
}()
在 validator 了解到区块的内容后,他们用自己的交易替换了一些交易。由于主网拒绝了之前的区块,因此恶意的 validator 不再需要与 relayer 竞争。新的区块随后被包含在主链中。
修复此问题的解决方案很简单,即检查错误并正确处理它们。
// Publish the signed beacon block via beacon-node
signedBeaconBlock := SignedBlindedBeaconBlockToBeaconBlock(payload, getPayloadResp)
code, err := api.beaconClient.PublishBlock(signedBeaconBlock) // errors are logged inside
if err != nil {
log.WithError(err).WithField("code", code).Error("failed to publish block")
api.RespondError(w, http.StatusBadRequest, "failed to publish block")
return
}
在这里,可以看到攻击者使用了少量的 WETH (0.03) 来测试是否有一个 MEV 机器人正在监控该池,并发现确实有一个。此外,攻击者在攻击发生的前一天再次探测了 mev bot 的存在。
经过以上漏洞分析,攻击过程非常清晰。恶意的 validator 将原定用于钓鱼 MEV 机器人的交易,替换为实际区块中用于耗尽 MEV 机器人的交易。这样一来,替换后的三明治攻击将不再成功,从 MEV 机器人未能出售的情况可以看出这一点。在此区块中,共有 5 个 MEV 机器人被耗尽。
以图中圈出的攻击交易为例,让我们分析一下攻击过程。
首先,MEV 机器人将 2,239.826266714477656208 WETH 兑换为 8.541715061486530888 BitDAO,导致 BitDAO 的价格上涨。
然后,MEV 机器人希望在“肉饼”交易中将 WETH 兑换为 BitDAO。然而,恶意的 validator 替换了“肉饼”交易的原始方向,转而将 BitDAO 兑换为 WETH。结果,攻击者通过将 223.355371927574958667 BitDAO 兑换为 2,239.829243108673760552 WETH,耗尽了 MEV 机器人的流动性池。
最终,MEV 机器人尝试将 BitDAO 出售为 WETH 的尝试失败了,因为攻击者已经在交易之前兑换了所有可用的 WETH。
那么攻击者从哪里获得了 BitDAO 呢?事实证明,它是在攻击发生前 16 天以 0.07 ETH 的价格从 Uniswap V3 兑换的。
此问题的核心漏洞位于 relayer 模块中,该模块在未成功广播的情况下暴露了区块的内容。乍一看,这似乎是一个无害的疏忽,因为交易已经是公开的。然而,重要的是要注意,Flashbots 的交易池是私有的。这可以作为一个教训,说明暴露私有交易池可能会导致潜在的安全风险,应立即解决。
https://ethereum.org/zh/developers/docs/consensus-mechanisms/pos/block-proposal/
https://news.marsbit.co/20230404092014806342.html
https://www.odaily.news/newsflash/318588
https://web3caff.com/zh/archives/56823
https://github.com/flashbots/mev-boost-relay/pull/330
https://twitter.com/samczsun/status/1642848556590723075
- 原文链接: medium.com/@zan.top/mev-...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!