精品项目

DeFi干货

2024-11-07 15:35:42



以太坊虚拟机EVM及 Solidity 智慧合约问世后,重入攻击事件频传。本文 Amber Group 安全团队将分享并解析他们在 8 月所发现币安智能链BSC项目 Dexfolio 的 LPFarming 合约漏洞案例。前情提要:DeFi 干货Dinosaur Eggs 的流动性池漏洞解析 Amber 安全团队

本文由Amber Group 研究团队撰着、提供。

在以太坊虚拟机EVM及 Solidity 智慧合约问世后,短短数年间内就出现了许多重入攻击事件。 2021 年 8 月 15 日,我们发现币安智能链BSC项目 Dexfolio 的 LPFarming 合约存在一个可被重入攻击的漏洞,并透过漏洞悬赏平台 ImmuneFi 通报了这个漏洞。

由于 Dexfolio 研发团队并未在过去的 120 天内公布事后剖析报告,因此我们将在本篇文章中提供相关细节。

0x00 Dexfolio

Dexfolio 的 LPFarming 合约可让用户以质押资产的方式来进行流动性挖矿。 对于用户所持有的每项资产,LPFarming 合约提供了四个公用函数处理质押任务。

例如:LPFarmingstake() 函数可让使用者将币安币BNB转入合约,并将半数的 BNB 转换为 DEXF 代币,用以铸造 DEXFWBNB LP 代币后,质押 LP 代币。

从上方的程式码片段可看到,在第 555 行 newBalance 由当前余额扣掉原始余额 initialBalance 计算出新铸造的 DEXFBNB LP 代币数量。在第 560 行,新的质押记录被加入了 stakes[] 阵列,作为计算挖矿奖励的依据。

0x01:漏洞

在这四个质押函数中,stakeToken() 是一个较为特殊的函数,它可以让使用者透过支付任意一种 ERC20 代币来交换 DEXFBNB LP 代币以作为质押资产。

然而,我们发现此处并未具有防止重入的 nonReentrant modifier。由于使用者可以传入任意的 fromTokenAddress 执行 stakeToken(),因此很多的 ERC20 函数调用 (例如 transfer()、transferFrom() 及 approve() 等) 都可能被用于劫持控制流程或重入 stakeToken()。

在上方的第 647 行程式码中可以看到,initialBalance 备份了后续代币交换前的余额以便计算第 651 行新铸造的 DEXFBNB LP 代币数量。然而, 649 行的 swapAndLiquifyFromToken() 调用在内部执行了 fromTokenAddressapprove(), 以利在 PancakeSwap 上交换代币。

这使得不法分子可于原始 stakeToken() 调用的主体内嵌入另一个质押操作,导致 651 行的 newBalance 变大。 简言之,攻击者可能会针对同一批 LP 代币进行双重质押。

例如,攻击者调用 stakeToken(10),并透过另一个帐户及 fromTokenAddressapprove() 嵌入另一个 stakeToken(90)。 最终,第一个帐户持有 10 90 = 100 个质押的 LP 代币,而第二个帐户则持有 90 个,后者的 90 在此处经过了重复计算。

乍看下,因为第二个帐户必须执行某些程式码才能重入 stakeToken(),故第 638 行的 isContract 检查可防止重入。 然而,在 LPFarming 里的 isContract 的实作无法涵盖所有情况,例如在 constructor 里就能实现绕过检查的恶意程式码。

0x02:漏洞利用

为利用重入漏洞,我们需要一个恶意 ERC20 合约 (Ftoken) 来劫持 approve() 调用。 一如下方的程式码片段所示, Ftoken 透过 optIn 开关覆写了 OpenZeppelin ERC20 实作的 approve() 函数。

当开关开启时,创建 Exp 合约并在其 constructor 中嵌入上文提及的 stakeToken() 调用,以便避开有漏洞的 isContract 检查。

由于 LPFarming 的 isContract modifier 仅检查某地址对应的 extcodesize,我们可透过执行 Exp 合约中建构函数 (constructor) 里的 LPFarmingstakeLPToken() 来绕过保护机制,如下所示。

若真的很希望避免使用合约帐户,则须确保检查 txorigin == msgsender。

此处遗漏了一个部分。由于 stakeToken() 在 PancakeSwap 将 fromTokenAddress 资产转换成 DEXFBNB LP 代币,我们必须创造 FtokenBNB 对并增加其流动性。我们透过另一个 Lib 合约来实现此一目的。

下方的 Libtrigger() 函数可使我们在 PancakeSwap 上创造 FtokenBNB 对,并将与 Ftoken 数量相同的 WBNB 放入流动池中。 此外,我们也加入了一个 Libsweep() 方便 owner 在完成攻击后搜刮流动池中所有剩余的 WBNB。

备妥这三份合约后,我们就可以进行实验以验证我们的理论。 如下方 ethbrownie 截图所示,我们先从 21 WBNB 开始,并部署了 Ftoken 及 Lib 合约。

eth钱包官网

如前所述,我们使用 Exp 合约的 constructor 来重新质押部分 LP 代币并通过 LPFarminggetStakes() view function 可以观察到 Exp 合约目前所持有的份额数量。

由于 Exp 合约需要 LP 代币用于重新质押,但直到 Ftokenapprove() 中 Exp 才会被创造,如此处所示范的 [1],我们用 Ftoken 合约地址预先以 ethutil 计算出 Exp 地址,并且将 LP 代币转过去。

准备好 Ftoken 及 Lib,并以 Libtrigger() 创造 FtokenBNB 对后,我们便可执行第一个 stakeToken() 发起重入攻击。

如上图所示,我们在 stakeToken() 调用前后均执行 FtokenoptIn(),以便启动及切换 Ftokenapprove() 中的劫持机制。

最后,我们用 LPFarmingemergencyWithdraw() 提取 LP 代币的数额并转换为 WBNB。 此外, 我们也执行 Libsweep() 以便获取 FtokenBNB 流动池中其余的 WBNB。

最终我们取得了 1936 WBNB,并在 LPFarming 合约中留下 Exp 合约的质押记录。 由于 Exp 合约已部署于 Ftokenapprove() 调用中,我们无法重新初始化合约以及在 constructor 中再次执行 LPFarmingemergencyWithdraw(),因此,攻击者似乎无法从中获利。 然而实际上,CREATE2 指令可使我们能够重新初始化 Exp 合约。

0x03 CREATE2

CREATE2 指令是以太坊 Constantinople 硬分叉后的产物,能使用户透过特定合约的位元组程式码及 salt 值预先计算合约地址。 伴随而来的结果是,如果合约以 SELFDESTRUCT 指令自毁,同样的位元组程式码及 salt 值可能会再次被部署在同一个地址上。

利用这个特性,我们可以让 Ftokenapprove() 部署 Exp 合约并执行重入后执行 SELFDESTRUCT。之后,我们可重新部署 Exp 合约并执行 LPFarmingemergencyWithdraw() 以提取双重质押的 LP 代币。

上图显示了变更后的 Ftokenapprove()。有四个参数传递至 CREATE2 调用。 第一个 0 代表创造合约时支付了 0 以太币,最后一个 0 是 salt 值,其应与重新建立合约时的值相同。 第二、第三个参数均与我们要部署的位元组程式码相关。

除了变更后的 Ftokenapprove() 外,我们还新增了 getAddress() view 函数以预先计算 Exp 合约地址。 我们在这里只须根据 EIP1014,以 0xff、创建者地址及 32 位元组的 salt 值及合约程式码 bytecode。

除了上述的修改,我们也调整了 Exp 合约,根据 token 合约所保持的状态来质押或提取 LP 代币,并以 SELFDESTRUCT 指令自毁的方式允许下次的重新部署操作。

在 CREATE2 的帮助下,我们的 Exp 合约便可赚取利润,如下方截图所示:

我们成功地在区块高度 10181384 从 LPFarming 合约中获取 1558 个 LP 代币,并将其转换为 WBNB。

0x04:事件的时间轴与致谢

我们在 2021 年 8 月 15 日将此问题回报给 ImmuneFi 平台 [2], 且 Dexfolio 团队已要求使用者于 2021 年 8 月 20 日提取其资产 [3]。在我们通报之后,ImmuneFi 随即告知我们,此漏洞报告有可能是重复回报,但须与 Dexfolio 团队确认。

由于我们已逾 90 天未能从 ImmuneFi 或 Dexfolio 得到回应,因此我们选择以独立研究的方式揭露细节。 在我们表示有意揭露细节后,ImmuneFi 便为这份有效的报告向我们适当地揭露流程,于 2021 年 11 月 26 日赠予我们 1000 美元等值的以太币ETH以作为奖励。 此外,ImmuneFi 也协助我们联系了最初回报同样漏洞的白帽骇客 lucashdev。

关于 Amber Group

成立于 2017 年,业务遍及亚洲及欧美各大主要城市,现为 1000 多家知名大型机构客户提供加密金融服务,在 100 多个电子交易所中累计交易总额已超过 1 兆美元,资产管理规模超过 40 亿美元,帮助客户管理各种加密资产的风险,提供灵活化的投资、最大化的回报来优化长期价值

DeFi干货

Amber Group官方网站: wwwambergroupio

WhaleFin官方网站 wwwwhalefincom

若有产品相关问题,请联系 Amber 客服团队 [emailprotected]、[emailprotected]

相关报导

Amber Group估值涨10倍达10亿镁、AUM20亿镁,加密金融独角兽正野心扩展全球!全解析 不可不知的 3种Defi重入攻击 基本概念、背后细节、手法 Amber资安负责人干货 Amber 安全专家吴博士:剖析 BSC 的闪电贷攻击手法,如何再引发 3 个分叉项目连环爆?

LINE 与 Messenger 不定期为大家服务