“我杀我自己?”—— MonoX.Finance安全事件分析_EFI:ONO

前言

11月30日,知道创宇区块链安全实验室?监测到自动做市商协议MonoX.Finance遭黑客攻击,损失超3100万美元。实验室第一时间跟踪本次事件并分析。

简述攻击流程

本次攻击分析选用以太坊交攻击交易:

0x9f14d093a2349de08f02fc0fb018dadb449351d0cdb7d0738ff69cc6fef5f299

1、黑客首先通过swapExactTokenForToken函数将0.1WETH兑换为79.9MONO

Web3隐私系统Espresso Systems完成3200万美元融资,红杉资本参投:3月7日消息,Web3应用程序扩展和隐私系统EspressoSystems完成3200万美元融资, Greylock Partners 和 Electric Capital 领投,红杉资本、Blockchain Capital 和 Slow Ventures参投。

据悉,Espresso Systems 正在开发第 1 层区块链基础设施,通过将权益证明共识协议与zk rollup机制集成来提供快速、低费用的交易。该项目的以太坊可配置资产隐私 (CAPE) 智能合约应用程序旨在为创建者提供有关发送方和接收方地址以及持有或移动资产的数量和类型的可定制隐私。这些元素都可以设置为公共、私人或仅对选定方透明,将支持 ERC-20 代币的创建和包装,未来还将支持NFT。(Coindesk)[2022/3/7 13:43:02]

2、重复利用函数removeLiquidity移除Monoswap合约中的流动性,直至全部移除

动态 | 红杉合伙人Roelof Botha美国银行账户遭关闭,加密爱好者劝说其拥抱加密货币:红杉合伙人、Paypal前首席财务官Roelof Botha发推称,其作为20年的美国银行账户,该行在未说明任何理由的情况下决定关闭其账户。目前在Roelof Botha的推文下方,包括BoostVC董事总经理Adam Draper在内的众多加密货币爱好者纷纷留言,建议Botha拥抱加密货币。[2019/11/18]

3、通过函数addLiquidity添加自己操控的流动性

4、重复调用函数swapExactTokenForToken实现MONO->MONO的不合理兑换

业内观点:红杉起诉币安的形式意义大于赔偿结果:据全天候科技,某一线VC基金的投资人认为,红杉之所以要起诉币安,形式的意义大于赔偿的结果:“一个一线美元基金如果对这种事忍让,那就称不上一线基金。”也有观点认为,在币安这种明星项目上,对于红杉来说丢了项目不能丢了气场,打官司至少还可以向LP们证明已经尽力了。对于赵长鹏而言,此次遭红杉起诉可能还会有信誉损失。有投资人表示,“看到他这么对待别人就会担心以后这么对待自己。”[2018/4/27]

5、最终利用被以上操作抬高价格的MONO兑换了WETH、WBTC、MONO、USDC、USDT、DUCK、MIM、IMX等从而获利。

动态 | Monero计划于11月30日进行升级:昨日在Monero开发者会议上,开发者决定了Monero拟议升级计划的时间表,预计于11月30日进行升级。此次升级将冻结代码,这意味着开发人员不能再做任何更改。此外还包括网络升级。为了享受更新后的最新功能,用户需要将他们的系统升级到CLI v0.15或GUI v0.15。除了这些小的升级之外,还有大量的重大更改。首先,此次升级将集成一个新开发的长期工作量证明算法,即RandomX。此外,将消除长支付ID,从而增强用户体验。最后的更新将包含传入事务的锁定时间,将固定为十个区块。所有这些措施都对改善Monero网络上现有的隐私功能至关重要。(ambcrypto)[2019/9/25]

漏洞成因分析

分析攻击流程可以发现两个不合理的地方:

攻击者可以通过函数removeLiquidity移除了其他人添加的流动性

攻击者通过函数swapExactTokenForToken不断重复MONO兑换MONO的操作

检查源码

对函数removeLiquidity源码进行分析

可以看到函数removeLiquidity和它包含的内部函数_removeLiquidityHelper都没有对调用者进行权限限制,以及对需要被移除流动性的传参地址to进行验证,这导致了任意地址都能进行对该pool内所有流动性进行移除

对函数swapExactTokenForToken源码进行分析

1、发现函数swapExactTokenForToken主要功能由函数swapIn实现,对函数swapIn进行跟进分析

2、发现获取token信息的函数getAmountOut,对函数getAmountOut进行跟进分析

3、发现tokenInPrice与tokenOutPrice的计算规则相同都是通过函数_getNewPrice计算,跟进到函数_getNewPrice

4、发现price的获取对应两种状态

SELL状态:价格=代币初始价格*代币存储量/(代币存储量+费用)

BUY状态:价格=代币初始价格*代币存储量/(代币存储量-费用)

很明显相同token在BUY状态下获取到的价格大于SELL状态

5.回到swapIn函数,当传入token价格被获取到后会按照token种类通过_updateTokenInfo进行token信息更新。

由于传入的token都为MONO所以:

当通过if(tokenIn==address(vCash))判断时,MONO获取到的价格是SELL状态下计算的价格;

当通过if(tokenOut==address(vCash))判断时,MONO获取到的SELL状态下的价格会被BUY状态下获取的价格覆盖;

因此当发生MONO兑换MONO操作时,MONO的价格会上升。

重新梳理攻击过程

第一步:黑客将0.1WETH兑换为79.9MONO作为启动资金

第二步:黑客移除了pool内全部流动性,防止攻击受到影响或者价格波动被检测到

第三步:黑客添加了自己控制的流动性,便于兑换操作

第四步:黑客通过重复MONO兑换MONO的操作,不断抬高MONO价格

第五步:利用已经被抬高的MONO兑换pool内其他资产达到获利目的

总结

本次安全事件问题其实并不复杂,主要原因在于monoswap合约在设计时没考虑到特殊情况下的价格覆盖问题,而可任意移除流动性的缺陷则更加方便黑客对于价格的操纵。

来源:金色财经

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

金宝趣谈

[0:0ms0-3:627ms