1. 前言
北京时间 2022 年 03 月 13 日,知道创宇区块链安全实验室监测到BSC
上Paraluni
项目遭到攻击,黑客获利约 170 万美金。知道创宇区块链安全实验室将对本次事件深入跟踪并进行分析。
2.分析
2.1基础信息
攻击者地址:0x94bc1d555e63eea23fe7fdbf937ef3f9ac5fcf8f
攻击者合约:0x4770b5cb9d51ecb7ad5b14f0d4f2cee8e5563645
攻击交易哈希:0x70f367b9420ac2654a5223cc311c7f9c361736a39fd4e7dff9ed1b85bab7ad54
Masterchef 合约:0xa386f30853a7eb7e6a25ec8389337a5c6973421d
UBT代币合约(攻击者创建):0xca2ca459ec6e4f58ad88aeb7285d2e41747b9134
UGT代币合约(攻击者创建):0xbc5db89ce5ab8035a71c6cd1cd0f0721ad28b508
2.2项目背景
Paraluni 项目是新加坡 Parallel Universe 基金会发布的一个基于币安智能链的匿名项目,用户可以通过与masterChef
合约交互进行质押代币获取流动性收益。
2.3攻击流程
为了使得攻击流程更加清晰,我们将本次攻击分为两个阶段进行分析。
预攻击阶段
1.攻击者创建部署两个代币合约UBT和UGT。UBT:改写transferFrom函数,实现对MasterChef的deposit()
函数和withdrawAsset()
函数的调用。UGT:ERC20代币标准的代币合约2.攻击者使用闪电贷从pancakeSwap借出156,984 BSC-USD和157,210 BUSD。3.将借出的USDT和BUSD向对应的ParaPair添加流动性,获得155,935枚Paraluni LP代币到UBT合约中。此时获取的Lp代币为后续的攻击提供重要支持。
核心攻击阶段
1.调用 MasterChef 合约中的 depositByAddLiquidity 函数,传入参数为_pid
:18,_token
:[UGT,UBT],_amounts
:[1,1],表示向 18 号池子添加 1 个UGT 和 1 个 UBT 的流动性。
2.然后内部调用depositByAddLiquidityInternal 函数,该函数的主要作用是调用 addLiquidityInternal 函数去铸造 LP 代币,然后调用_deposit
函数存入 LP 代币到用户地址。但是函数并未校验用户传入的_tokens
和池子编号为_pid
的 tokens 是否匹配,这就造成攻击者能够利用自己创建部署的恶意代币进行后面重要操作。
3.depositByAddLiquidityInternal 再内部调用 addLiquidityInternal 函数,该函数通过合约中 LP 代币余额变化计算出需要 deposit 的数量。
4.其中当 addLiquidityInternal 函数调用到 paraRouter.addLiquidity 时,会调用攻击者在预攻击阶段部署的 UBT 代币合约中的 transferFrom 函数完成添加流动性操作。
但该恶意合约改写 transferFrom 后会调用 MasterChef 的 deposit() 函数将预攻击阶段第三步获取的 LP 代币转入 masterChef 中,此时的 masterChef 中 LP余额 已经变化,然后会调用 _deposit 函数存入 LP 代币到用户地址,此时获取第一份 LP 代币。
然后加上恶意合约的 transferFrom 调用 deposit() 时也会调用 _deposit 函数存入 LP 代币到用户地址,就相当于获取了两份LP代币。
5.攻击者分别调用 UBT 合约中的 withdrawAsset 函数和利用攻击合约调用 Mastechef 合约中的 withdraw 函数提取两份相同的LP 到攻击合约中;
6.最后移除流动性获取 31 万枚 BSC-USD 和 31 万枚 BUSD,然后归还闪电贷完成攻击。
3.漏洞核心
本次的攻击主要是MasterCheif 合约中的 depositByAddLiquidity函数并未校验用户传入的_tokens
和池子编号为_pid
的tokens是否一致,且外部调用时并未考虑到重入问题添加重入锁,最终导致攻击者能够传入外部恶意代币合约进行重入攻击。
4.总结
知道创宇区块链安全实验室在此提醒,任何有关deposit等操作都需要慎重考虑,合约审计、风控措施、应急计划等都有必要切实落实。