Morpheus智能合约爆重大安全漏洞,原因为大小写错误

大文
大文

Jun 27, 2018

摘要: 该漏洞是由于大小写编码问题,导致任何以太坊账户均可调用该函数夺取合约的所有权,进一步实现盗币等系列非法操作。

链得得注:本漏洞由知道创宇提供。知道创宇成立于2007年,是国内最早提出云监测与云防御理念的网络安全公司,于2015年再次获得腾讯大范围战略投资。知道创宇创始人及CEO赵伟入选2012年《福布斯》30位30岁以下创业者之一。知道创宇云安全平台目前服务全国90万网站,包括国家公安部、国务院中央政府采购网、工信部、CNNVD、央行、香港赛马会、微软、浙江卫视等。

一、漏洞概述

以太坊智能合约的含义就是一组代码(函数)和数据(合约的状态),它们位于以太坊区块链的一个特定地址上。智能合约一般使用solidity语言编写。

Morpheus Network与世界上一些大型航运、海关和银行公司协商,通过利用区块链的智能合约技术建立一个全面服务的、全球性的、自动化的、开放的供应链平台和一个集成的加密货币支付系统 ,发布基于以太坊的 MorphToken。

2018年6月22日,Morpheus Network 发公告称将发布新的智能合约,以更新目前含有漏洞的合约代码。新的Token名称为MRPH,新旧Token以1:1兑换。

随后,知道创宇404区块链安全研究团队开始漏洞应急,通过分析MorphToken合约代码和交易历史,确定该漏洞是由于大小写编码问题,错误的将Owned合约的构造函数Owned的首字母小写,使之成为了一个普通函数owned,任何以太坊账户均可调用该函数夺取合约的所有权,进一步实现盗币等系列非法操作。随即我们发布了相关应急报告,同时我们也注意到BCSEC安全团队发布了相关的分析文档。

在后续的研究中,我们发现早在2017年8月29日,Github上就有人提到了这种因构造函数缺失导致的合约安全漏洞问题。该漏洞目前影响包括MorphToken、B2X、DoubleOrNothingImpl等多个智能合约。

二、漏洞原理

在MorphToken的合约代码里可以明显的看到相关大小写编写错误:

以太坊智能合约中的构造函数主要用于初始化,如:确定合约的所有者,并且只会在合约部署时运行。在小于0.4.22版本的solidify编译器语法要求中,构造函数的名称应该和合约名称保持一致。如果程序员在编写合约时将构造函数名称写错,那么原本的构造函数将成为任何人都可以调用的普通函数。漏洞示例代码及在Remix-ide中的复现结果如下:

0x01 漏洞合约部署

下图中,Bank合约继承自Owned合约。在Owned合约中,由于错误的编码,将构造函数名称写错,owned函数成为了一个普通函数。可以看到,Bank合约部署后,由于缺少构造函数,初始化时owner为0x0000000000000000000000000000000000000000。

0x02 漏洞现场还原

任何以太坊账户都可以调用Bank合约继承自Owned合约的owned函数,更改Bank合约的owner变量,从而使合约所有权发生转移。

如下如所示,0x14723a09acff6d2a60dcdf7aa4aff308fddc160c这个账户调用了Bank合约的owned函数后,可以看到Bank合约的owner变成了0x14723a09acff6d2a60dcdf7aa4aff308fddc160c。同理,攻击者也可以利用这个漏洞提权,实施一系列恶意操作。

三、漏洞影响评估

我们使用内部的以太坊智能合约审计系统对以太坊主链上所有30000+公开智能合约进行了自动化审计,确认受该大小写编码漏洞影响的共计16个,以下为统计结果:

(受漏洞影响程度取决于合约的逻辑,具体代码审计结果可联系知道创宇404区块链安全研究团队)

理论上在合约部署后,由于编码错误引起的构造函数缺失,owner默认值会变为0x0000000000000000000000000000000000000000,这样合约中涉及到owner的函数调用都会异常,合约所有者应该能及时发现漏洞才是。然而MorphToken这种市值几百万美金的代币,因为合约存在这个编码漏洞而被盗币。通过分析Morph Token源代码,我们得到了答案。MorphToken继承了Owned合约,但是自己实现了构造函数。就是说,是父合约向外留了一个“后门”。

另一种情况,如果合约中没有涉及owner权限的函数调用,那么即使攻击者盗取了合约所有权,也没有任何用处。上表B2X合约中就是这种情况。

总体来说,受漏洞影响的合约数量不多,属于被MorphToken带着“火”了一把的漏洞。

事实上,很多安全漏洞都来源于程序员的粗心编码,智能合约这种部署后即不可更改的更应加强代码审计。

四、防护方案

0.4.22版本以后的solidity编译器引入了constructors关键字,以替代低版本的将合约名作为构造函数名的语法,从而避免程序员编码错误。强烈建议采用最新版本编译器。

链得得仅提供相关信息展示,不构成任何投资建议
本文系链得得原创,未经授权不得使用,如需获取转载授权,请点击这里

更多精彩内容,关注链得得微信号(ID:ChainDD),或者下载链得得App

分享到:

相关推荐

    评论(0

    Oh! no

    您是否确认要删除该条评论吗?

    分享到微信