前言
11 月 21 日,知道创宇区块链安全实验室 监测到以太坊上的 DeFi 协议 Formation.Fi 遭遇黑客攻击,损失近 10 万美元。实验室第一时间跟踪本次事件并分析。
涉及对象
Vault:
0xcb6afdc84e8949ddf49ab00b5b351a5b0f65a723
TetherToken:
0xdac17f958d2ee523a2206206994597c13d831ec7
黑客地址:
0x6510438A7E273e71300892c6faf946aB3B04CbCb
攻击合约地址:
0xd02C260F54997146C9028b2Ac7144b11ce4c20a6
攻击流程及形成漏洞成因分析
简述攻击流程
1、首先黑客通过 合约 0xd02C 进行闪电贷借出启动资金 200 USDT
2、向合约 Vault 质押 100 USDT 获得 99 Formation USD
3、通过 Vault 合约 swapin 函数置换 100 USDT 并附带大量 fee
4、调用 Vault 合约函数 withdraw 销毁 99 Formation USD 获得漏洞利润 99999 USDT
5、最后归还闪电贷 将获利转到黑客地址
漏洞成因分析
检查源码后发现具体问题主要出在 Vault 合约函数 swapIn 上,可以看到该函数调用参数 fee 能影响记录着全部代币的变量 totalTokens 的计算, fee 越大 totalTokens 越大。
而在通过函数 withdraw 实际获取利润时,可以看到实际转账时 totalTokens 参与了计算,所以当大量的 fee 被带人 totalTokens 计算后,会造成 withdraw 函数的转账超过原本的转账金额。
而造成攻击获利巨大的另个原因是 Formation USD 与 USDT 的小数点数位不同,Formation USD 为 18 位,USDT 为 6 位。小数点精准数位的差距在实际转账中进一步放大了黑客的收益。
Vault:
TetherToken:
重新梳理攻击过程
第一步:选用 USDT 作为攻击使用的代币,目的 USDT 与 Formation USD 的小数点精确度不同
第二步:黑客质押 100 USDT,目的为了后续调用 withdraw 函数实现套利
第三步:黑客兑换 100 USDT,目的添加大量的 fee 提升 totalTokens 的值
第四步:黑客取回质押的 USDT,目的使用提升后 totalTokens 与利用代币间小数点精确度不同来套取利润
第五步:归还闪电贷,转移套取的利润
总结
本次闪电贷安全事件发生的主要原因在于项目方设计函数 swapIn 时低估了 fee 对 totalTokens 的影响,且忽视了不同代币间小数点精确度的影响。
知道创宇区块链安全实验室 再次提醒近期各链上频频爆发攻击事件,合约安全愈发需要得到迫切重视,合约审计、风控措施、应急计划等都有必要切实落实。
|