3月9日消息,DODO的wCRES/USDT资金池遭受攻击,攻击者转走了价值约90万美元的wCRES和价值约113万美元的USDT。DODO是一个近期很热门的DeFi项目。攻击者利用资金池合约的初始化函数漏洞,从资金池盗取了 133,548.93858472505wCRES 1,139,456.204397USDT。 DODO官方发推表示,此次攻击只和DODO V2众筹池有关,作为预防措施,已经关闭DODO资金池创建入口。 通付盾区块链安全团队(SharkTeam)第一时间对此事件进行了攻击分析和技术分析,并系统地总结了安全防范手段,希望后续的区块链项目可以引以为戒,共筑区块链行业的安全防线。 攻击分析 通过分析攻击发生的交易0x395675b56370a9f5fe8b32badfa80043f5291443bd6c8273900476880fb5221e可以发现,造成损失的整个攻击过程非常简单。攻击者将FDO和FUSDT两种空气币转入wCRES/USDT资金池,并通过DODO闪电贷借出 133548.93858472505个wCRES 1139456.204397个USDT 为什么攻击者可以用两种空气币成功从闪电贷借出wCRES/USDT呢?此次攻击的执行trace如下图所示。上方红框表示攻击者向资金池转入FDO和FUSDT的过程,下方红框表示攻击者向资金池借贷的过程。 可以看到攻击者在调用flashLoan函数的过程中执行了init初始化函数,并且输入的 baseTokenAddress参数为FDO, quoteTokenAddress参数为FUSDT。通过分析源码中的init函数可知,攻击者利用该函数将资金池重新进行了初始化,此时资金池被重新初始化成了FDO/FUSDT池。因此,攻击者可以规避闪电贷的贷款归还机制。 通过分析可以发现,DODO资金池的初始化函数init没有对调用者的权限进行严格的校验,也没有做一些防止重复调用的措施,这才导致攻击者可以轻易的重新初始化资金池。 智能合约安全问题分析 在文章《权限问题再掀波澜,PAID Network安全事件分析》中我们分析了PAID Network因为私钥泄露引起的安全事件以及其他两个因为权限问题引起的安全事件,即Furucombo无限授权漏洞以及ICX Token交易控制Bug;此外还分析了3类与权限相关的智能合约安全漏洞。本文中,将继续分析3类与权限相关的漏洞,如下: 1.无保护地调用自毁 漏洞原因:selfdestruct(Address address)函数可以销毁当前合约,并且把当前合约的余额发送给指定地址(address)。因此,selfDestruct调用时若没有权限限制,则任意账户都可以调用该函数销毁合约,造成合约剩余的Token的巨大损失,进一步则会引发合约拒绝服务攻击,从而引起及其严重的后果。 错误代码:任意用户都可以调用kill方法销毁合约。 修复建议:对函数selfdestruct的调用进行权限的限制,确保只有通过了验证的账户才可以调用selfdestruct函数。正确实现如下: 正确实现时增加了对调用selfdestruct自毁函数的权限管理,只有 0x564BcA365D62BCC22dB53d032F8dbD35439C9206才能调用selfdestruct自毁函数。其中 0x564BcA365D62BCC22dB53d032F8dbD35439C9206是合约owner账户地址。 2.函数默认可见性 漏洞原因:函数的可见性可以声明为external,public,internal或private。默认情况下,未指定可见性的函数其可见性默认是public。如果开发人员忘记设置可见性,恶意用户能够进行未经授权或意外的状态更改,则可能导致漏洞。 错误代码:_sendWinning函数未声明可见性,默认为public,这导致任意账户都可以调用_sendWinning函数修改balance,从而绕过withdrawWinnings函数中的条件。 修复建议:显示地声明所有函数的可见性 (external,public,internal或private),这可以大大减少合约系统的攻击面。正确实现如下: 正确实现是将_sendWinnings函数声明为internal,该函数只能在合约内部使用,调用该函数只能通过withdrawWinnings函数。另外,显示地指明withdrawWinnings的可见性为public。 3.基于代理的可升级合约中未加保护的初始化器 漏洞原因:由于基于代理的可升级性系统的要求,在可升级合同中不能使用构造函数。这意味着,在使用带有OpenZeppelin升级程序的合同时,您需要将其构造函数更改为常规函数,通常命名为initialize,在其中运行所有设置逻辑。但是,Solidity中可以多次调用常规函数。若是没有权限控制,则initialize函数可以调用多次,智能合约也会被初始化多次。 错误代码:初始化函数initialize缺少权限限制,因此可以被多次调用,合约也会被多次初始化。 修复建议:在初始化函数initialize中添加权限限制。正确实现如下,修复后的代码能够保证只会初始化一次。 通付盾安全建议 通付盾建议您在智能合约开发过程中,请确保合约业务逻辑上的严密性,对于特殊功能函数,如构造函数、初始化函数、转账函数、铸币函数,甚至是任何一个可以修改状态变量的函数,在满足业务需要的情况下,应对其访问和调用权限要做严格的管理和限制,因为这些函数都与合约的状态变量甚至是Token有直接的关系,任意一种权限使用不当都会使合约存在极大的风险。 另外在项目上线前应进行严格的智能合约审计,提高合约的安全性。扫描文章顶部二维码,注册登录通付盾DTC平台,使用通付盾智能合约审计服务。 |
智能合约安全问题再暴雷,DODO资金池被盗事件分析
