Popsicle攻击事件复盘分析 | 零时科技

Popsicle攻击事件复盘分析 | 零时科技

事件背景

Popsicle Finance是专注于自动做市(AMM)流动性提供商(LP)的下一代跨链收益提高平台。旨在成为一个完全分散的平台,由其用户(ICE治理令牌的持有者)管理。ICE令牌将用于对协议更新,资产池包含,费用管理以及协议其他关键运营方面的提案进行投票。

零时科技区块链安全情报平台监控到消息,北京时间2021年8月4日,Popsicle Finance官方推文称Sorbetto Fragola被攻击,零时科技安全团队及时对该安全事件进行复盘分析。

Popsicle攻击事件复盘分析 | 零时科技

事件分析

攻击信息

通过初步追踪分析,攻击者创建了3个攻击合约,进行了1笔攻击交易,共盗取资金价值超2100万美元,攻击信息如下:

攻击者钱包地址:

https://cn.etherscan.com/address/0xf9E3D08196F76f5078882d98941b71C0884BEa52

攻击者合约地址:

合约1:

https://cn.etherscan.com/address/0xdFb6faB7f4bc9512d5620e679E90D1C91C4EAdE6

合约2:

https://cn.etherscan.com/address/0x576cf5f8ba98e1643a2c93103881d8356c3550cf

合约3:

https://cn.etherscan.com/address/0xd282f740bb0ff5d9e0a861df024fcbd3c0bd0dc8

攻击交易:

https://cn.etherscan.com/tx/0xcd7dae143a4c0223349c16237ce4cd7696b1638d116a72755231ede872ab70fc

SorbettoFragola合约地址:

https://cn.etherscan.com/address/0xc4ff55a4329f84f9Bf0F5619998aB570481EBB48#contracts

攻击过程

攻击者在一笔交易中,利用同一攻击手法进行了多次获利,下面分步解析该笔交易,方便读者更清晰的了解攻击过程。

Popsicle攻击事件复盘分析 | 零时科技

第一步:攻击合约1从Aave利用闪电贷借出3000万枚USDT,1.3万枚ETH,1400枚BTC,3000万枚USDC,300万枚DAI,20万枚UNI。

第二步:攻击者合约1通过Uniswap V3协议使用5492枚WETH和3000枚USDT添加流动性并获取10.52枚Popsicle LP。

第三步:攻击者合约1将获取的10.52枚Popsicle LP发送至攻击者合约2,后者又将LP发送至攻击者合约3,最后将LP归还至攻击者合约1。

第四步:攻击者合约1归还获取10.52枚Popsicle LP,得到添加流动性的5492枚WETH和3000枚USDT。

第五步:攻击者合约2和合约3分别从Uniswap V3优化器SorbettoFragola得到392枚ETH和215万枚USDT(凭空获利)。

交易信息中,攻击中循环执行8次同样的攻击(第二步至第五步)。

Popsicle攻击事件复盘分析 | 零时科技

第六步:攻击者合约2和合约3将获取到的资金全部转至攻击者合约1。

第七步:攻击者归还闪电贷的3000万枚USDT,1.3万枚ETH,1400枚BTC,3000万枚USDC,300万枚DAI,20万枚UNI及其手续费。

第八步:攻击者将获取的资金统一转至攻击者钱包。

至此

攻击者通过该笔攻击交易获取了497万枚USDT,2560枚ETH,96枚BTC,538万枚USDC,16万枚DAI,1万枚UNI,总价值超过2100万美元。

走到这里大家可能会有疑问,交易的第三步为什么将LP多次转移,交易第五步为何会获取大量代币,下面我们从合约中分析SorbettoFragola合约代码逻辑。

攻击成功的原因

通过以上交易分析可以明确,攻击者将LP在攻击合约2和攻击合约3中转移后,这两个攻击合约就分别获取了大量资金,我们从交易logs信息中可查找出具体调用的合约调用事件,如下图:

Popsicle攻击事件复盘分析 | 零时科技

从上图的信息我们可以发现,攻击者合约2触发了两次RewardPaid事件,分别是有LP时的触发和最后将LP转移走后的触发,但两次事件显示传入方法的参数截然不同,第一次为0,第二次为获利资金,我们继续分析RewardPaid事件对应的合约中collectFees方法,如下图:

Popsicle攻击事件复盘分析 | 零时科技

上图collectFees方法中,RewardPaid事件触发需要进行三个主要判断:

  1. 修饰符执行updateVault(msg.sender);
  2. 判断奖励user.token0Rewards >= amount0;
  3. 判断(balance0 >= amount0 && balance1 >= amount1);

这里条件二是由updateVault(msg.sender)更新得到,只要获取的amount数值不超过奖励数值,均可完成该条件;条件三只要amount不超过对应合约余额,则该条件成立;下面继续分析条件一:修饰符updateVault(msg.sender),如下图:

Popsicle攻击事件复盘分析 | 零时科技

调用_updateFeesReward方法,继续跟进,如下图:

Popsicle攻击事件复盘分析 | 零时科技

上图updateFeesReward方法中,调用的第一个方法为pool.positionLiquidity,主要判断流动性是否为0,这里不做详细解释,我们主要来看获取奖励user.token0Rewards和user.token1Rewards变量相关联的四个方法:earnFees,tokenPerShare,fee0Earned,fee1Earned。

_earnFees方法,主要功能是获取Uniswap pool中的奖励数值,如下图:

Popsicle攻击事件复盘分析 | 零时科技

_tokenPerShare方法,主要功能是通过earnFees方法中获取的奖励值来计算每个 LP 代币提供了多少代币,如下图:

Popsicle攻击事件复盘分析 | 零时科技

fee0Earned,fee1Earned方法中,通过每个LP代币提供的代币数量,计算特定的用户可以获得多少token,如下图:

Popsicle攻击事件复盘分析 | 零时科技

这里非常重要的一点是:

整个奖励计算流程中,只要user.token0Rewards奖励计算出来后,如果不提取奖励,该值不会再受到减少的影响,只可能通过fee0Earned方法更新不断增大。

攻击流程到这里就比较清晰了,攻击者合约1将LP转至攻击者合约2后,攻击者合约2随即调用漏洞合约的collectFees方法更新奖励值,随后将LP转出,由于user.token0Rewards奖励值只会叠加,并且该方法中并未判断调用者是否拥有LP,之后攻击者合约2再次调用collectFees方法获取user.token0Rewards奖励。

从以上攻击流程可以看出,攻击者利用SorbettoFragola合约未判断LP的归属问题,借助闪电贷资金,多地址移动LP并调用collectFees方法,多次循环操作后,获取大量代币。

总结

通过此次攻击事件来看,攻击者通过闪电贷资金,并通过SorbettoFragola合约未判断LP的归属问题,最终获得了大量代币,目前类似的闪电贷攻击事件居多,为何还会频频发生,对于DeFi项目而言,合约代码的安全,代币价格的相对稳定,旧版本的及时更新都是保证项目安全极其重要的部分,对于合约未判断LP的归属问题,应在合约上线前进行严格审查及测试。对于此类闪电贷攻击事件,零时科技安全团队给出以下建议:

安全建议

  • 对于合约代码安全,可找多家安全审计公司进行审计。
  • 对LP归属及获取奖励判断,应根据业务逻辑进行严格审核演算,避免出现参数可控导致盗币问题。
  • 对转账地址应进行严格判断,避免转账地址异常导致参数可控。
  • 使用可信的并且安全可靠的预言机,如Chainlink去中心化预言机,Alpha homera采用的。
  • 对敏感性较强的代码,要做到及时更新完善。

原创文章,作者:西链财经,如若转载,请注明出处:http://www.xilian.link/depth/75760.html