查看原文
其他

【区块链智能合约安全系列】MEV Bot 被反向套利损失 2500万美元

蚂蚁技术AntTech 蚂蚁技术AntTech
2024-08-22

随着区块链技术的广泛应用,智能合约已经成为区块链应用开发的重要组成部分。然而,智能合约的安全问题一直是亟待解决的难题。针对区块链智能合约中的一些常见漏洞问题,本专栏将对多个案例进行分析和研究,帮助读者更好地了解智能合约的漏洞类型、攻击方式和防范措施。本篇文章是蚂蚁安全天宸实验室区块链智能合约安全系列文章中的第 3篇,希望能为广大读者提供一些有价值的参考和帮助,共同提高区块链应用的安全性,促进区块链技术的进一步发展。


01
事件回顾

北京时间 2023 年 4 月 3 日,多个 MEV bot 在以太坊 16964664 这一区块被黑客攻击。一名恶意验证者替换了 8 笔交易,导致 5 个 MEV bot 共损失约 2538 万美元。我们经过分析发现,攻击者早在 35 天前就开始为攻击做全面的准备了,毫无疑问,此次攻击是一次长期的预谋。


TokenLost AmountLost Amount
WBTC64.905$1,828,568.57
USDC5297649.983$5,297,649.98
USDT3027396$3,036,478.19
DAI1698384$1,701,780.77
WETH7460.809243$13,525,253.43
Total
$25,389,730.94

调查显示,攻击目标主要瞄准 Flashbots 的 MEV bot,被攻击的 MEV bot 如下:

0x00000000008C4FB1c916E0C88fd4cc402D935e7D

0x00000000008C4FB1c916E0C88fd4cc402D935e7D

0x000000000035B5e5ad9019092C665357240f594e

0x00000000003b3cc22aF3aE1EAc0440BcEe416B40

0xE8c060F8052E07423f71D445277c61AC5138A2e5


02背景知识
什么是 MEV/MEV Bot
MEV的全称是“最大可提取价值”(Maximum Extractable Value)。在区块链技术中,MEV 是指通过重新排序或者删除区块中的交易,从而潜在地获取区块奖励、交易手续费等的一种策略。MEV bot 是一种通过自动化程序来获取区块链网络中 MEV 的方法。这种方法基于区块链网络中的交易顺序和交易手续费等因素,通过自动化程序自动挖矿、交易等操作,从而实现获取 MEV 的目的。

以太坊 PBS 协议
在当前以太坊的协议层设计中,区块构建者(Builder)和区块提议者(Proposer)是同一实体——在PoS之下,他们被称为验证者(Validator)。要想成为验证者,用户必须向合约存入 32 ETH。这种 Builder 和 Proposer 作为同一实体的设计会导致严重的中心化问题。于是,PBS(Proposer-Builder Separation)一种把 Proposer 和 Builder 分离的协议被提出。PBS 的核心理念之一是,Proposer 在签名前不能看到他要签名的块的内容。直到块被广播出去,Proposer 才可以获知所签名的块的内容。


03
漏洞分析

三明治攻击

MEV bot 会不断追踪用户在交易池中的交易,以寻找套利机会。它们经常进行所谓的“三明治攻击”,即在用户交易的前后分别放置一笔交易,将其“夹在中间”,形成一个三明治组合。例如,检测到用户希望用 A 买 B的交易后,MEV bot 会抢先发送一笔用 A 买 B 的交易,推高 B 的价格,让用户以较高的价钱买入B,用户买入后,B 的价格会被推的更高,之后,MEV bot 会再发送一笔交易把 B 卖成 A,通过这种“三明治”的操作,获得其中的利差而盈利。


核心漏洞

此次事件的关键问题出在恶意的验证者替换了原有的交易内容,使得原本可以通过三明治手段收割他人的 MEV bot 成为被收割的对象,并且成功的让修改后的区块被主网接收。


正常情况下,使用 Flashbots 服务的验证者是无法做到修改区块内容并被主网接受的,原因如下:

  1. 验证者在签署交易的时候无法事先知道交易内容。Flashbots 实现了 PBS 协议,Proposer 在签名前不能看到他要签名的块的内容。验证者无法获知所签署的内容,也就无从下手了。

  2. 签署完成后,Flashbots 的 relayer 会快速把区块广播到主网中,这时候交易内容也被公开。验证者此时虽然可以获知交易内容,但是要修改交易内容,并且要让修改后的区块被主网接受,需要跑赢 relayer,这是十分困难的。


那么恶意验证者是如何做到让修改后的区块被主网接收的?


实际上,恶意验证者是确定自己一定能够跑赢 relayer 的。TA 利用了这样一个漏洞:Flashbots 的 mev_boost_relay 模块没有正确处理区块出现错误的情况。当出区块现错误时,广播会失败,aka,区块不会被主网接收,但是 mev_boost_relay 依然返回了区块内容。这就让恶意验证者能够获知交易内容,进而得以替换交易。并且由于前一个区块广播失败,修改后的区块就不需要赛跑,而是直接被主网接收。


恶意验证者只需要制造一个简单的错误,就可以达成攻击目标。来看恶意验证者第一次提交的区块内容。

图片来自 sumczsun 的 tweet


这个区块的 parent_root 和 state_root 都是 0,显然是一个非法区块。relayer 把这个区块广播到主网,因为是一个非法区块,显然会被主网拒绝。但是 relayer 依然返回了交易的内容,给了攻击者可乘之机。以下代码可以看到,mev_boost_relay 模块没有处理 PublishBlock() 的错误,广播区块如果失败了,依然会公开区块内容。代码片段如下:

// 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 }()


意验证者在获知区块内容之后,替换了其中的交易。把交易顺序和交易内容替换成收割 MEV bot 的内容。并且被打包到主网。因为主网拒绝了最开始的区块,那么恶意验证者就不需要跟 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    }

链接如下:

https://github.com/flashbots/mev-boost-relay/blob/65e2b6c69dd91a49765f2f86d4cc70ed2509fed5/services/api/service.go



04
攻击过程

成为验证者

  1. 在区块号 16835415(Mar-15-2023 07:36:47 PM +UTC) - 16835844(Mar-15-2023 09:04:23 PM +UTC) 之间,从 Aztec 取回 32 ETH 作为攻击启动资金。

  2. 在区块号 16836204(Mar-15-2023 10:17:35 PM +UTC) 抵押 32 ETH 到合约,待成为验证者。

    tx id 

    0x9cf11fde666d94b32ee9ba3fc6aee468b03f2f5e7ef06f1642415fe0ebfe7c58

  3. 在 epoch 187922(Mar-16-2023 05:01:11 PM + UTC) 被激活成为验证者。

  4. 在区块号 16964664(Apr-02-2023 11:29:35 PM +UTC)被选作 proposer,并发起攻击。

  5. 恶意的验证者因为违反了提案规则,在攻击发生当天已经被惩处。有关此恶意验证者的信息可以查看 https://beaconcha.in/validator/552061


攻击者从准备资金成为验证者,到被选作提案者,历经 18 天。成为验证者是此次攻击的重要前提。



 小额试探

这里能看到攻击者在 18 天前有一个小额的试探过程,发现的确有 MEV bot 在监控池子。而且,攻击者在实施攻击的前一天,再一次试探了 MEV bot 的存在。



链接如下:https://etherscan.io/address/0xD3FB891D4D5977F913AED30B752F2B1 78479dFdC#tokentxns



攻击过程

经过上一节的漏洞分析,攻击手段就很明确了。恶意的验证者终于等来了时机,被选作提议者,恶意验证者故意签署一个非法的区块,并且因为漏洞的原因,获知了交易内容。然后恶意验证者重新提议了一个有效的区块,在真正有效的区块中,把原本用于钓鱼 MEV bot 的原始交易,替换成收割 MEV bot 的攻击交易。这样替换后的三明治攻击就无法成功了。可以看到 MEV bot 在卖出时都失败了。本区块一共 5 个 MEV bot 被收割。


我们以图中圈出来的一笔攻击交易为例,来分析攻击过程。其他的攻击交易也是相似的过程,就不再赘述。


首先,MEV bot 用 2,239.826266714477656208 WETH 换取了8.541715061486530888 BitDAO。让 BitDAO 的价格升高。

然后,MEV bot 本来期待的是“牛肉饼”也是用 WETH 换取 BitDAO,这时候因为 BitDAO 的价格升高了,所以“牛肉饼”的收益将会减少。


但是,因为恶意验证者替换了原来“牛肉饼”的交易方向,替换为用 BitDAO 换取 WETH,即,用 223.355371927574958667 BitDAO 换取了 2,239.829243108673760552 WETH。这样一来,基本上把 MEV bot 的 WETH 全部兑换出来了,收割了 MEV bot 的资金池。

最后,MEV bot 的用 BitDAO 换 WETH 的卖出交易就失败了。因为攻击者抢先一步把 WETH 全部兑换出来了。



那么,攻击者的 BitDAO 是从哪里来的呢?原来是在攻击发生的 16 天前 (Mar-17-2023 02:31:35 PM +UTC) 从 Uniswap V3 用 0.07 ETH 换来的。

链接如下:

https://etherscan.io/tx/0x704c026491686621d24639cd8c0cb534f1e546fd33179eb2b30a9fa63798f738



那么 V2 版本的交易对是谁创建的?原来,是攻击者在攻击发生的 34 天前(Feb-28-2023 01:53:35 PM +UTC) 创建的。创建的启动资金是从 V3 版本兑换而来。



至此,可以梳理出攻击者在这一交易对的时间脉络。攻击者观察到了 V3 版本存在 BitDAO 和 ETH 的交易对,而 V2 版本没有此交易对。所以攻击者首先在 V3 版本兑换出小额的代币,然后在 V2 版本上创建此交易对,并且制造 V2 和 V3 的利差,以此来引诱 MEV bot 上钩,并利用漏洞,反向套利 MEV bot。攻击者的心思不可谓不细腻。



完整时间线

至此,我们方能纵观整个事情的全貌,梳理一个完整的攻击时间线。

  1. 在区块号 16720011-16819877 期间(Feb-27-2023 02:05:47 PM +UTC - Mar-13-2023 03:11:47 PM +UTC),攻击者从 KuCoin 10 陆续获取攻击启动资金,共有 8 个攻击账号被授资。

  2. 在区块号 16726920-16828052 期间(Feb-28-2023 01:21:23 PM +UTC - Mar-14-2023 06:44:35 PM +UTC),攻击者开始创建 V2 版本的交易对,并且开始试探是否有 MEV bot 来监控交易。试探发现有 MEV bot 上钩后,攻击者注册成为验证者。

  3. 在区块号是 16835415-16835844 期间(Mar-15-2023 07:36:47 PM +UTC - Mar-15-2023 09:04:23 PM +UTC) 从 Aztec 取回 32 ETH 作为参选验证者的启动资金。

  4. 在区块号 16964664(Apr-02-2023 11:29:35 PM +UTC)被选作提议者,并发起攻击。


从最初的攻击准备 Feb-27-2023 02:05:47 PM +UTC 到发动攻击 Apr-02-2023 11:29:35 PM +UTC,历时 35 天。而这些只是呈现在幕前的时间,幕后的攻击准备时间恐怕只有攻击者自己知道。


05
总结

本漏洞的核心出现在 mev_boost_relay 模块 -- 没有广播成功,但是却公开了交易的内容。乍看之下,像是一个无害的疏忽,以太坊的交易本来就是公开的,如果没有提交成功,那公开也无妨吧。然而,需要注意的是,Flashbots 的交易池是私有的,私有交易在上链之前不应该被公开。这是一个教训,说明了私有交易池的曝光可能会导致潜在的安全风险,应该及时解决。

所有的攻击都是长期的预谋。攻击者非常谨慎,小心,早在 35 天前,攻击者就在试探并预谋攻击,当发现有 MEV bot 上钩后,注册成为验证者,然后静待被选作提议者这一时机的到来。




参考链接:

https://ethereum.org/zh/developers/docs/consensus-mechanisms/pos/block-proposal/

https://docs.flashbots.net/flashbots-mevboost/introduction

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://www.chaincatcher.com/article/2085119


区块链智能合约安全系列分享持续更新中,敬请期待

——————剧透————

第一篇:完整起底Euler攻击事件

第二篇:TornadoCash 遭受恶意治理攻击完整始末

第三篇:MEVBot 反向套利事件追踪

第四篇:Checks-Effects-Interactions魔咒:以太坊DeFi平台2500万美金被盗



继续滑动看下一个
蚂蚁技术AntTech
向上滑动看下一个

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存