2024 年 3 月 28 日,Prisma Finance 遭受闪电贷攻击,项目方损失约 1221 万美元。
SharkTeam 对此事件进行了技术分析,并总结了安全防范手段,希望后续项目可以引以为戒,共筑区块链行业的安全防线。
一、攻击交易分析
攻击者 1:0x7e39e3b3ff7adef2613d5cc49558eab74b9a4202(简记为 0x7e39)
攻击合约 1:0xd996073019c74b2fb94ead236e32032405bc027c(简记为 0xd996)
攻击者 2:0x7fe83f45e0f53651b3ed9650d2a2c67d8855e385
攻击合约 2:0x4148310fe4544e82f176570c6c7b649290a90e17
被攻击的目标合约:0x1cc79f3f47bfc060b6f761fcd1afc6d399a968b6
攻击包含 16 笔交易,以第一笔攻击交易为例:
0x00c503b595946bccaea3d58025b5f9b3726177bbdc9674e634244135282116c7
攻击流程如下:
1. 读取地址 0x56a201b872b50bbdee0021ed4d1bb36359d291ed(简记为 0x56a2)在目标合约中的所有抵押物和债务。
返回结果如下:
地址 0x56a2 在目标合约中抵押物共有 1,745 wstETH,总债务共有 1,442,100 mkUSD。
2. 攻击者 0x7e39 通过攻击合约 0xd996 调用 mkUSD 债务合约中的 flashLoan 函数。
参数 receiver 设置为 MigrateTroveZap,amount 为上面查询到的全部债务。
然后,在 flashLoan 函数中会调用 receiver(这里是 MigrateTroveZap)中的 onFlashLoan 函数。
onFlashLoan 函数通过闪电贷先偿还原来的所有债务,提取抵押物到 receiver,然后 receiver 将一定数量的抵押物重新抵押,并借取一定的债务。其中主要调用了 2 个函数:
(1)closeTrove 函数,偿还债务并将所有的抵押物(1745.08 swtETH)从 troverManager 提取到 receiver(这里是 MigrateTroveZap 合约);
(2)openTrove 函数,由 receiver 将 463.18 wstETH 重新抵押到 troverManager 中,并负债 1,443,598 mkUSD。
从上面数据可以看出,flashLoan 函数执行完成后,receiver 中仍然保留了从 troverManager 中提取的属于地址 0x56a2 的抵押物,数量约为 1745.08 – 463.18 = 1281.90 wstETH。
3. 攻击者 0x7e39 通过攻击合约 0xd996 从 Balancer 中通过闪电贷借取了 1 wstETH。
然后,抵押 1 wstETH 并借取债务 2000 mkUSD,加上 fee,共计负债 2200 mkUSD。
4. 与步骤 2 类似,调用 mkUSD 债务合约中的 flashLoan 函数,这里参数 receiver 仍然设置为 MigrateTroveZap,amount 为上一笔质押 1 wstETH 后的全部债务,即 2000 mkUSD。在 FflashLoan 函数中会调用 receiver 中的 onFlashLoan 函数,然后调用 closeTrove 和 openTrove 函数。
只是,这里 closeTrove 和 openTrove 函数中的参数 account 不再是上面的地址 0x56a2,而是质押了 1 wstETH 的攻击合约 0xd996。
(1)closeTrove 函数,偿还债务并将所有的抵押物(1 swtETH)从 troverManager 提取到 receiver(这里仍然是 MigrateTroveZap 合约)。此时 receiver 中共有 1281.90 +1=1282.90 wstETH.
(2)openTrove 函数,由 receiver 将 1282.80 wstETH(几乎全部)重新抵押到 troverManager 中,并负债 2001.8 mkUSD。
实际上,这里抵押物中 1281.80 wstETH 是不属于攻击合约 0xd996,而是属于上面的地址 0x56a2。
5. 最后,攻击者 0x7e39 通过攻击合约 0xd996 单独调用 closeTrove 函数,将抵押的 1282.80 wstETH 提取到了攻击合约 0xd996 中。
偿还闪电贷后,攻击者仍获利 1281.80 wstETH,约 2.30M USD。
二、漏洞分析
本次事件的根本原因是项目合约存在逻辑和权限校验,使得攻击者可以利用该漏洞获取其他账户地址的质押资产。
攻击者最终获得的 wstETH 是原本地址 0x56a2 在 troverManager 合约中的抵押物,通过 mkUSD 合约的 flashLoan 函数,自定义 MigrateTroveZap 合约中 onFlashLoan 函数的参数,利用 MigrateTroveZap 将其转变为攻击合约的抵押物,然后将其提取出来。
攻击者通过 mkUSD 合约中的 flashLoan 函数以及 MigrateTroveZap 合约中的 onFlashLoan 函数操纵其他账户地址的抵押和提取。
(1)flashLoan 函数中缺少对参数 receiver 地址的校验,因为 onFlashLoan 函数中 receiver 会接收 account 的所有抵押物,因此需要对 receiver 进行可信的校验;
(2)onFlashLoan 函数中缺少对 account 地址的校验,因为 closeTrove 和 openTrove 函数都是操作的 account 的资产,因此需要对 account 增加权限方面的校验;
除了对这两个地址参数的校验外,可能还需要对 flashLoan 函数中的数量参数以及实现逻辑进行校验。
三、安全建议
针对本次攻击事件,我们在开发过程中应遵循以下注意事项:
(1)项目在设计和开发过程中,要保持逻辑的完整性和严谨性,尤其是涉及到资产的转移过程中,更要加强对函数调研权限的校验,保证调用者、调用函数、函数参数、转账逻辑等都是安全可信的。
(2)项目上线前,需要找专业的第三方审计团队进行合约审计。
About Us
SharkTeam 的愿景是保护 Web3 世界的安全。团队由来自世界各地的经验丰富的安全专业人士和高级研究人员组成,精通区块链和智能合约底层理论。提供包括风险识别与阻断、智能合约审计、KYT/AML、链上分析等服务,并打造了链上智能风险识别与阻断平台 ChainAegis,能有效对抗 Web3 世界的高级持续性威胁 (Advanced Persistent Threat,APT)。已与 Web3 生态各领域的关键参与者,如 Polkadot、Moonbeam、polygon、Sui、OKX、imToken、Collab.Land 等建立长期合作关系。
官网:https://www.sharkteam.org
Twitter:https://twitter.com/sharkteamorg
Telegram:https://t.me/sharkteamorg
Discord:https://discord.gg/jGH9xXCjDZ
【免责声明】市场有风险,投资需谨慎。本文不构成投资建议,用户应考虑本文中的任何意见、观点或结论是否符合其特定状况。据此投资,责任自负。