SharkTeam:BH 闪电贷攻击原理分析
BNB Chain
Web3
支付
对于依托 LP 中的代币价格的计算逻辑,更要严格审计,避免出现操纵价格的情况。
撰文:SharkTeam
北京时间 2023 年 10 月 11 日,BNB Chain 上的 BH 代币遭受攻击,攻击者获利约 120 万美元。
SharkTeam 对此事件第一时间进行了技术分析,并总结了安全防范手段,希望后续项目可以引以为戒,共筑区块链行业的安全防线。
一、事件分析
攻击者地址:
0xfdbfceea1de360364084a6f37c9cdb7aaea63464(简记为 0xfdbf)
攻击合约:
0x216ccfd4fb3f2267677598f96ef1ff151576480c(简记为 0x216c)
0xf040735f8619d8615cf0ee532f58c106c4924300(简记为 0xf040)
被攻击合约:
0x8ca7835aa30b025b38a59309dd1479d2f452623a(简记为 0x8ca7)
攻击交易:
0xc11e4020c0830bcf84bfa197696d7bfad9ff503166337cb92ea3fade04007662
攻击流程如下:
1. 攻击者从多个合约中通过闪电贷借入共计 26,521,678 USDT
。
(1)攻击合约 0x216c 通过攻击合约 0xf040 调用 flashloan 函数借入 1,521,678.713 USDT;
(2)攻击合约 0x216c 调用 Uniswap 的 2 个 LP 合约中的 swap 函数借入 25,000,000 USDT。
通过两种闪电贷,攻击者共借入 26,521,678 USDT。
2. 循环调用被攻击合约中的 Upgrade 函数,共计 12 次。Upgrade 函数包含以下 5 个功能:
(1)调用者将 USDT 转移到被攻击合约;
(2)将 10% 的 USDT 转移至 0xc9fc938bcf691affa79c9fec3d1719f6297fa20e;
(3)将 60% 的 USDT 添加流动性到 USDT/BH-LP 合约中,其中 BH 直接从被攻击合约中扣除;
(4)将剩余的 30% 通过 USDT/BH-LP 合约兑换成 BH;
(5)将兑换的 BH 转账给指定地址。
该 Upgrade 函数主要功能是将调用者转入的 USDT 的 60% 添加流动性,流动性中的另一种 BH 代币则直接由被攻击合约 0x8ca7 支付。
因为调用 Upgrade 函数会将 30% 的 USDT 兑换 BH。因此,每调用一次 Upgrade 函数,USDT/BH-LP 中 BH 价格上涨。在调用 Upgrade 前 USDT 与 BH 的比例大约为 1:96。
循环调用 12 次 Upgrade 函数,攻击者共添加流动性 79,672.096,转移 13,590 USDT。因进行兑换的数量相比于 LP 合约中的代币余额很小,因此,USDT 与 BH 的比例几乎未变,大约仍为 1:96。
3. 调用被攻击合约中的 0x33688938 函数,如下:
通过该函数,攻击者共添加流动性 19,487,579.804,转移 3,000,000 USDT。在该函数执行完成后,USDT 与 BH 的比例变为 1:57,BH 的价格上涨。
4. 通过 PancakeSwap,将 22,000,000 USDT 兑换成 209,261,023 BH。
因兑换的代币数量很大,兑换成功后,USDT 与 BH 的比例变为 1:1.6,BH 的价格暴涨。
5. 环调用被攻击合约中的 0x4e290832 函数,共计 10 次。0x4e290832 函数主要是溢出流动性,这一点恰与 Upgrade 函数相反,其同样包含 5 个功能,如下:
(1)销毁 BH,即将 BH 从攻击合约 0x216c 转移到被攻击合约 0x8ca7,然后销毁(即再次转移至零地址)。销毁数量为调用 0x4e290832 函数传递的参数。该参数是 LP 合约中 BH 余额的 55%,该比例定义在攻击合约 0x216c 中,由交易 inputdata 传入合约。
(2)溢出流动性。根据销毁的 BH 数量,计算出需要溢出的流动性,然后移除流动性,获得 USDT 和 BH。
从数量上看,销毁的 BH 数量与移除流动性获得的 BH 数量相近。因此,移除流动性获得的 USDT 数量是根据 LP 中 BH 的价格(USDT 和 BH 的数量比例)来计算的。BH 价格越高,获得的 USDT 越多。
(3)USDT 转移。将获得的 USDT 的 85% 转移到攻击合约 0x216c 中。因为 BH 价格被太高,因此可以获得更多的 USDT。
(4)添加流动性。将获得的 USDT 的 10% 重新添加流动性。
(5)兑换。将获得的 USDT 剩余的 5% 兑换成 BH,BH 价格再次被抬高。因为兑换数量较少,BH 价格被抬高的也相对不明显。
循环调用 10 次 0x4e290832 函数,因 BH 价格被太高很多,所以可获得更多的 USDT。另外,在第二次调用 0x4e290832 函数时,移除的流动性依然超过攻击者添加的总流动性。在本次攻击交易中,除了抬高了 BH 的价格外,0x4e290832 函数在移除流动性时并未限制流动性的数量,使得攻击者移除了部分被攻击合约中原有的 LP,从而获得了额外的利益。
循环调用 10 次 0x4e290832 函数,攻击者共收到 26,358,571 USDT,比闪电贷的 25,013,590 USDT 多出 1,344,981 USDT。
6. 闪电贷还款,包括闪电贷的手续费,并将剩余的 1,275,981 USDT 转移给攻击者地址 0xfdbf。
二、漏洞分析
本次攻击利用了被攻击合约的 0x4e290832 函数中的漏洞,通过抬高 BH 的价格,最终获利。其中包含了 2 个漏洞:
(1)0x4e290832 函数移除流动性时并没有检查移除的流动性数量是否超过其添加的流动性,业务上并不严谨;
(2)0x4e290832 函数在计算移除的流动性数量时是根据参数中的 BH 数量以及 LP 中的 BH 价格计算得到的,而添加流动性时的 BH 是由被攻击合约提供,因此,操纵 BH 价格可以让攻击者在移除流动性时获得更多的 USDT。
本次事件中,攻击者利用这两个漏洞发起攻击,获得了大约 120 万美元。
三、安全建议
针对本次攻击事件,我们在开发过程中应遵循以下注意事项:
(1)严格检查业务逻辑,避免业务中的不严谨逻辑。对于依托 LP 中的代币价格的计算逻辑,更要严格审计,避免出现操纵价格的情况。
(2)项目上线前,需要向第三方专业的审计团队寻求技术帮助。
免责声明:
1.资讯内容不构成投资建议,投资者应独立决策并自行承担风险
2.本文版权归属原作所有,仅代表作者本人观点,不代表Bi123的观点或立场