GRI:Grim Finance 闪电贷安全事件分析_Agricoin

0x01:前言

援引官方消息,北京时间12月19日,Fantom链上复合收益平台GrimFinance遭遇了闪电贷攻击。知道创宇区块链安全实验室第一时间对本次事件深入跟踪并进行分析。

0x02:事件详情

交易细节如下图所示:

浏览上图的交易过程可知,攻击合约利用闪电贷借取代币WFTM和BTC,将借取的代币与自己铸造的代币质押到SpiritSwap里增加流动性获取lp代币,而问题就出现在攻击者通过depositFor()实现质押的过程中。

通过Tenderly调试该笔交易,攻击者多次递归调用depositFor函数,利用该函数获取大量代币:

风投机构Griffin Gaming Partners为其游戏基金募资7.5亿美元:3月7日消息,风险投资机构Griffin Gaming Partners宣布推出其超额认购的第二只基金,获得至少7.5亿美元的出资承诺。虽然该基金关注更广泛的游戏行业,但Griffin Gaming Partners联合创始人Phil Sanderson和Nick Tuosto表示,迄今为止已经有16笔与Web 3相关的投资,占已部署资本的一半以上。

据悉,Griffin的Fund II出资方包括主要机构、大学捐赠基金、家族办公室、主权财富基金和游戏行业的战略合作伙伴。

Griffin投资游戏内容、软件基础设施和社交平台以及与游戏相关的Web 3公司,参与从种子轮到增长轮的投资。其投资组合公司包括区块链游戏平台Forte和消息应用程序Discord。(CoinDesk)[2022/3/7 13:43:06]

前众议院议长Newt Gingrich希望中央银行持有比特币,以对冲通胀:10月24日消息,美国前众议院议长纽特·金里奇 (Newt Gingrich) 担忧通胀,他建议各国应在其货币储备中持有比特币,以对冲通胀。Gingrich目前是以色列公司国际比特币咨询公司 (IBAC) 的顾问,他认为新兴经济体将从采取这样的行动路线中受益最大。(zycrypto)[2021/10/24 6:10:31]

0x03:漏洞分析

depositFor()函数位于的第1115行:

function?depositFor(address?token,?uint?_amount,address?user?)?public?{

?uint256?_pool?=?balance();

Grin社区发布节点异常简报,Beam基金会负责人提醒Grin代码分支可能遭受相同攻击:Grin社区发布此前“GRIN节点出现异常”概述表示,Grin需要范围验证(rangeproofs),以确保负承诺值不会造成通胀情景。如果没有范围验证,就有可能创建交易输出,通过使用负值来人为地增加供给。如果没有有效的范围验证来验证输出是否为负值,恶意行为者就有可能创建包含负值输出以及高价值输出的交易,这些高价值输出似乎可以与“将创建0个新代币”平衡。在本例中,攻击者尝试利用漏洞“RangeProof的缓存验证优化中没有充分的验证”。Grin ++用户在验证中发现,并由Grin++开发人员David Burkett转发给Grin团队的其他成员,同时还提供了一个修复程序来缓解错误的rangeproof缓存逻辑。

Beam基金会负责人Guy Corem表示,多节点实现(multiple node implementation)拯救了此次恶意攻击。有一些Grin代码分支没有节点实现,很可能遭受了完全相同的攻击。

此前消息,Grin网络在区块高度1136081出现无效交易,原因是范围验证缓存逻辑错误。为此,Grin已经发布v5.0.4版本对此进行修复,用户须进行更新。[2021/3/21 19:04:31]

?IERC20(token).safeTransferFrom(msg.sender,?address(this),?_amount);

声音 | 财经博主:Grin匿名捐赠者即使不是中本聪 也应该是一位比特币早期开发者:财经博主比特币女博士发微博表示,中本聪最后一次“露面”,是在2011年4月给比特币早期开发者Gavin Andresen发了一封简短的邮件说到,“我要去搞别的事情了,Gavin与其他人会很好的接手比特币项目”,随后销声匿迹。最近给grin社区捐赠的50btc的地址,上一次有变动是在2010年的12月,所以这个捐赠者即使不是中本聪,也应该是一位比特币早期开发者。下图是这位神秘捐赠者留下的对grin的“祝福”,字里行间是一个很通情达理,情商很高的geek(极客),跟很多“后中本聪”完全不同。[2019/11/14]

?earn();

?uint256?_after?=?balance();

?_amount?=?_after.sub(_pool);?//?Additional?check?for?deflationary?tokens

动态 | Gate.io开通Grin充提服务:Gate.io发布公告称,已经开通Grin充值和提现服务,用户可以随时使用Gate.io平台交易和秒冲秒提Grin。[2019/1/31]

?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方法实现套利,而闪电贷?攻击者只是利用闪电贷扩大了套利值。

对于合约代码而言安全性是十分重要的,每一个未经验证的传入参数都可能导致巨大的经济损失,开发者在编写重要操作方法时,须记住零信任原则,谨慎对待每一个传入参数。

来源:金色财经

郑重声明: 本文版权归原作者所有, 转载文章仅为传播更多信息之目的, 如作者信息标记有误, 请第一时间联系我们修改或删除, 多谢。

大币网

[0:15ms0-5:468ms