2022年8月2日消息,跨链协议Nomad遭受到黑客攻击,损失超过1.9亿美元。
SharkTeam第一时间对此事件进行了技术分析,并总结了安全防范手段,希望后续项目可以引以为戒,共筑区块链行业的安全防线。
(资料图片)
一、事件分析
被攻击合约(代理合约):0x5d94309e5a0090b165fa4181519701637b6daeba
代理合约实现合约:0xb92336759618f55bd0f8313bd843604592e27bd8
以其中一笔交易为例,交易如下:
txHash: 0xb1fe26cc8892f58eb468f5208baaf38bac422b5752cca0b9c8a871855d63ae28
该交易中调用了process函数:
根据交易执行过程,并且对比了其他调用了process函数的交易,最终发现了问题所在:
在调用acceptableRoot函数时,输入的参数为0,即messages中并没有对应的消息,结果返回ture。acceptableRoot函数如下:
这里,参数_root是0,confirmAt的值是1,返回值是true。
confirmAt本身的表示_root被确认的时间,当_root为0时,实际是没有被确认过的,confirmAt的值应该也为0,最后会返回false。正是这一点小失误造成了巨大的经济损失,对整个项目造成了近乎毁灭性的打击。
另外,confirmAt[0]的值为什么会是1呢?
从合约中可以看出,合约的初始化函数initialize会将confirmAt的值初始化为1,初始化函数需要在合约部署后即刻调用,一般由合约的部署地址即owner账户来调用。
另外,setConfirmation函数也可以直接设置confirmAt的值,但只有owner账户才能调用。
我们查看了owner账户以及其所有的交易,发现是在初始化时将confirmAt[0]设置成了1。
owner: 0xa5bd5c661f373256c0ccfbc628fd52de74f9bb55
txHash: 0x53fd92771d2084a9bf39a6477015ef53b7f116c79d98a21be723d06d79024cad
该合约是升级后的合约,初始化函数是在合约升级后对合约进行初始化。对比于升级前的实现合约(0x7f58bb8311db968ab110889f2dfa04ab7e8e831b),初始化函数相同,但process函数是不同的,升级前的process函数如下:
因此,本次事件完全就是合约升级时的失误造成的,小小的失误却给合约和项目带来了致命的风险。
二、安全建议
引发本次安全事件的根本原因是可升级合约在合约升级的过程中存在失误,造成合约逻辑实现存在严重漏洞。
鉴于此,我们建议在使用可升级合约时要保持谨慎之心。尤其是在升级合约时,不仅要保证状态变量的正确性,也要保证逻辑处理没有漏洞。另外,选择专业的智能合约审计团队进行多轮审计,也是提高合约安全性的重要保障。
三、关于我们
SharkTeam的愿景是全面保护Web3世界的安全。团队成员分布在北京、南京、苏州、硅谷,由来自世界各地的经验丰富的安全专业人士和高级研究人员组成,精通区块链和智能合约的底层理论,提供包括智能合约审计、链上分析、应急响应等服务。已与区块链生态系统各个领域的关键参与者,如Huobi Global、OKC、polygon、Polkadot、imToken、ChainIDE等建立长期合作关系。