意识到位,可惜操作没跟上 — 详解 uniswapV2Call 风险

区块链安全 2年前 (2022) admin
883 0 0

前言

今天分享了一个关于 MEV BOT 因为 open uniswapV2Call 而被反撸的案例,这个风险之前就已经看到有人分享了,但是由于一直没有实际的案例,所以没办法总结成分享,这次正好借着blockSec分享的案例来详细分享一下关于 open uniswapV2Call 的风险。

什么是 uniswapV2Call

在 Uniswap V2 版本的 pool 合约中,存在一个功能称为 flash swap,即允许用户在 swap的过程中产生外部调用,然后实现一些用户想自定义的功能,比方说你想在 uniswapV2 兑换的同时在 sushiswap 也进行一次兑换,那么这个时候就可以利用上这个 flash swap 的功能,在 swap的中途穿插进 sushiswap 的调用。这里面说到的外部调用,其实就是通过 uniswapV2Call 来实现的,具体的代码如下:

意识到位,可惜操作没跟上 — 详解 uniswapV2Call 风险

意识到位,可惜操作没跟上 — 详解 uniswapV2Call 风险

不难发现,#172 行在 swap 函数中开了一个口子,当调用 swap 函数的时候指定的 data 参数长度不为 0 的时候,就会通过 uniswapV2Call 函数来对指定的 to 地址产生外部调用,同时我们可以注意到,uniswapV2Call 函数带上的参数分别为 msg.senderamount0Outamount1Out 和 data。这些参数都是为了方便外部合约在接受函数调用的时候可以做一些检查。好了,那么到这里,我们就已经明白这个函数究竟是做什么的了。那么下面我们就容易分析它的风险了。

open uniswapV2Call 的风险

open uniswapV2Call,其实可以统一定义为那些在接受 uniswapV2Call 调用的外部合约不检查 uniswapV2Call 函数里的 sender 的情况,这个 sender 又是什么呢?其实就是 uniswapV2Call 函数的第一个参数,在通过 uniswapV2Call 调用的时候,它总是被指定成当前调用 swap 函数的地址,也就是 msg.sender,而在其他情况下,如未鉴权的 uniswapV2Call函数,则这个 sender 可以是任意值。

那这个函数具体的风险是什么呢?从定义来看,open uniswapV2Call 其实就是因未检查 sender 函数而产生的可被人意调用的风险,针对这种风险通常有两种攻击场景 – 外部合约在定义 uniswapV2Call 函数的时候,完全没有任何的鉴权,允许任意调用 – 外部合约在定义 uniswapV2Call 函数的时候,只对来源地址进行了鉴权,要求必须是来自 pool 合约的调用

上面这两种攻击场景里,第一种就完全不用说了,明显的有问题,那第二种,已经鉴权了,还会有问题吗?针对这个问题,我们这次就以一个 MEV BOT 被反撸的案例来说说第二种情况的攻击方法

意识到位,可惜操作没跟上 — 详解 uniswapV2Call 风险

意识到位,可惜操作没跟上 — 详解 uniswapV2Call 风险

如上图所示,整个反撸其实分成3个阶段,分别是 – 闪电贷 – 使用闪电贷资金从 SLP 池中兑换将 WETH兑换成 PENDLE – 调用 sushiSwap 的 swap 函数,把 to 制定成要攻击的 MEV BOT合约,然后通过 sushiSwap 池来调用受害 MEV BOT 的 uniswapV2Call 函数。

那么,基于以上几个流程,攻击者是如何获利的呢?答案是这个 MEV BOT 实际上在做一种 PENDLE代币到 WETH 代币的操作,这个操作位于 MEV BOT 的 uniswapV2Call 函数内,而触发条件为合约内拥有一定量的 YT-SLP-29DEC2022 代币,为了满足这个条件,我们可以看到攻击者尝试给 MEV BOT 发送了少量的 YT-SLP-29DEC2022 代币才开始调用对应的 uniswapV2Call 操作。

结合这个 MEV BOT 的具体行为和攻击者的第二步,不难发现其实攻击者是为了通过闪电贷现在 SLP池中先创造一个大滑点,然后调用 MEV BOT 来继续兑换,此时,由于 MEV BOT 的接盘,导致对攻击者形成了利差,此时攻击者使用第二获得的 PENDLE 代币进行反向兑换即可完成对 MEV BOT 的反向套利。

意识到位,可惜操作没跟上 — 详解 uniswapV2Call 风险

意识到位,可惜操作没跟上 — 详解 uniswapV2Call 风险

整个流程就是如此,我们接下来看看 MEV BOT 合约的 uniswapV2Call 权限检查,通过反编译,不难发现 MEV BOT 合约本身只是检查了调用 uniswapV2Call 的来源地址是不是 pair 合约本身,但这是不够的,结合上文,由于 uniswapV2Call 调用是根据 to 地址发起的,所以其实任意人都可以通过调用pair中的 swap 函数同时将 to 指定成 MEV BOT 的合约来触发对 MEV BOT 合约的 uniswapV2Call 调用,这种情况下,调用的源地址,一定会是 pair 合约本身,但是整个流程,却不一定是你可控的。所以正确的方法是对 uniswapV2Call 的 sender 参数进行检查,判断调用是不是来自自己指定的或信任的地址。才能保证万无一失。本次的问题,合约的开发者很明显的意识到了权限的问题,但是可惜的是想的不全面,导致此次被反撸 8 ETH。

意识到位,可惜操作没跟上 — 详解 uniswapV2Call 风险

意识到位,可惜操作没跟上 — 详解 uniswapV2Call 风险

其他资料

  1. BlockSec 提供交易:https://ethtx.info/mainnet/0x6c30c0b8afe0596516c32ad6aa17566bfe29677ca4fe35a4a395210d28329d1f

  2. Flash swap介绍: https://docs.uniswap.org/protocol/V2/guides/smart-contract-integration/using-flash-swaps


原文始发于微信公众号(蛋蛋的区块链笔记):意识到位,可惜操作没跟上 — 详解 uniswapV2Call 风险

版权声明:admin 发表于 2022年5月25日 下午9:18。
转载请注明:意识到位,可惜操作没跟上 — 详解 uniswapV2Call 风险 | CTF导航

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
暂无评论...