0x01:前言
援引官方消息,北京时间12月19日,Fantom链上复合收益平台GrimFinance遭遇了闪电贷攻击。知道创宇区块链安全实验室第一时间对本次事件深入跟踪并进行分析。
0x02:事件详情
交易细节如下图所示:
浏览上图的交易过程可知,攻击合约利用闪电贷借取代币WFTM和BTC,将借取的代币与自己铸造的代币质押到SpiritSwap里增加流动性获取lp代币,而问题就出现在攻击者通过depositFor()实现质押的过程中。
通过Tenderly调试该笔交易,攻击者多次递归调用depositFor函数,利用该函数获取大量代币:
元宇宙游戏生态系统DeHorizon完成新一轮融资,Griffin Gaming Partners和Circle Ventures领投:2月18日消息,元宇宙游戏生态系统DeHorizon完成新一轮融资,Griffin Gaming Partners和Circle Ventures领投,融资规模未透露。DeHorizo??n将利用这笔资金孵化一系列游戏并扩大团队规模。(VentureBeat)
此前消息,元宇宙游戏生态系统DeHorizon宣布完成850万美元Pre-A轮融资,Sfermion、Dragonfly Capital、Everest Ventures Group领投,Animoca Brands、Yield Guild Games、Mechanism Capital、LD Capital、Zonff Partners、Jsquare、OKEx Blockdream Ventures等参投。[2022/2/18 10:01:35]
ZB中币集团与GRINOK笑脸矿业达成战略合作:据悉,ZB集团宣布与GRINOK笑脸矿业签署战略合作协议,双方就为矿工用户及区块链爱好者提供优质流动性服务达成深度合作。
ZB集团数字资产交易服务平台,服务超过1000多万海内外用户。GRINOK是一家综合性云算力采矿平台,活跃用户超过10万。
本次合作,一方面是为GRINOK矿工用户提供高效优质流动性服务;另一方面是为ZB平台区块链爱好者提供多元化产品。[2020/12/28 15:52:06]
0x03:漏洞分析
depositFor()函数位于的第1115行:
function?depositFor(address?token,?uint?_amount,address?user?)?public?{
动态 | 江卓尔点评Grin匿名捐赠事件:Grin是好币 唯一不酷的是价格:针对Grin开发基金收到50枚BTC匿名捐款一事,莱比特矿池CEO江卓尔今日在微博上发表点评:“其实Grin的确是好币,技术也酷,社区也酷,唯一不酷的就是价格。”江卓尔解释称,Grin价格不酷的原因是Grin后面有Core的几个大佬,“Grin实践的是Core产出不减半(恒定50币/块产出),总量无限的货币政策,由此可见Core路线的错误荒谬程度”。
「[2019/11/13]
?uint256?_pool?=?balance();
?IERC20(token).safeTransferFrom(msg.sender,?address(this),?_amount);
?earn();
现场 | Grin核心开发者Gary:早期的通货膨胀可以有效刺激消费:金色财经1月19日现场讯,“China First Grincon北京站”活动在1月19日下午举行。这场活动由Grin团队、币信、Primitive、区块律动共同举办。Grin团队开发者Gary出席了这场活动。Gary指出,Grin早期的通货膨胀可以很有效地刺激消费,而不是鼓励投机。从而让Grin更有可能成为应用型的基础币,更加健康,发展也更持久。Grin头4年的发行与比特币头4年的发行一模一样,都是线性增长。一个相对稳定的币价,使得10年后的矿工与之前的矿工相比,可以获得大致等量的奖励。Grin的公平是在时间线上对矿工的高度公平。[2019/1/19]
?uint256?_after?=?balance();
?_amount?=?_after.sub(_pool);?//?Additional?check?for?deflationary?tokens
动态 | Grin将完成首次出块:据MORECOIN研究院消息,Grin主网的第一个区块将在北京时间1月16日的00:01:27被挖出。[2019/1/16]
?uint256?shares?=?0;
?if?(totalSupply()?==?0)?{
??shares?=?_amount;
?}?else?{
??shares?=?(_amount.mul(totalSupply())).div(_pool);
?}
?_mint(user,?shares);
}
该函数的safeTransferFrom()方法从IERC20(token)调用,调用完该方法后,余额balance也会随之变动,最后通过_mint()方法向用户添加质押凭证代币。其中调用的变量token可控,导致攻击者可以自己实现safeTransferFrom()方法,将该方法重入到depositFor()发起攻击。
以实施了5次重入攻击为例,开始_pool的值为0,在重入depositFor方法的前四次里,攻击者一直传入自己铸造的代币,_pool的值会一直保持为0,但在第五次,也就是最后一次传入100个受认可的代币时,_after的值会变成100,而_afer-_pool的差值_amount也就是100,最后由于重入了5次,导致合约会向攻击者铸造100*5的质押凭证代币。
其后果就是攻击者向该合约质押自己铸造不受认可的代币,同样会增加质押总量,最后利用多出来的质押凭证实现套利。
0x04:修复方案
1.由于depositFor()方法里的token可控才是导致这次攻击事件的原因,因此只需要在传递参数的时候让token不可控就行:
function?depositFor(?uint?_amount,address?user?)?public
2.由于套利的原因是depositFor()方法里存在修改代币数量的函数,因此还可以将修改代币的方法单独实现,这样即使token变量可控,也无法成功套利:
function?depositFor(address?token,?uint?_amount,address?user?)?public?{
?IERC20(token).safeTransferFrom(msg.sender,?address(this),?_amount);
}
3.锁定交易token:
function?setLPToken(address?lp)?public?onlyOwner?{
lpToken?=?lp;
}
function?depositFor(uint?_amount,address?user?)?public?{
uint256?_pool?=?balance();
IERC20(lpToken).safeTransferFrom(msg.sender,?address(this),?_amount);
earn();
......
}
0x05:总结
经过完整分析,知道创宇区块链安全实验室明确了该次攻击事件的源头并非网传的闪电贷攻击,攻击者利用GrimBoostVault合约的depositFor方法参数可控,实施了重入攻击,将自己的铸造的无价值代币兑换成了质押凭证,最后通过withdrawAll方法实现套利,而闪电贷?攻击者只是利用闪电贷扩大了套利值。
对于合约代码而言安全性是十分重要的,每一个未经验证的传入参数都可能导致巨大的经济损失,开发者在编写重要操作方法时,须记住零信任原则,谨慎对待每一个传入参数。
来源:金色财经
郑重声明: 本文版权归原作者所有, 转载文章仅为传播更多信息之目的, 如作者信息标记有误, 请第一时间联系我们修改或删除, 多谢。