一、漏洞概述

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

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

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

随后,通过分析MorphToken合约代码和交易历史,确定该漏洞是由于大小写编码问题,错误的将Owned合约的构造函数Owned的首字母小写,使之成为了一个普通函数owned,任何以太坊账户均可调用该函数夺取合约的所有权,进一步实现盗币等系列非法操作。

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

二、漏洞原理

在MorphToken的合约代码里:https://etherscan.io/address/0x2ef27bf41236bd859a95209e17a43fbd26851f92#code 可以明显的看到相关大小写编写错误:

以太坊智能合约构造函数大小写编码错误漏洞-RadeBit瑞安全

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

0×01 漏洞合约部署

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

以太坊智能合约构造函数大小写编码错误漏洞-RadeBit瑞安全

0×02 漏洞现场还原

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

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

以太坊智能合约构造函数大小写编码错误漏洞-RadeBit瑞安全

三、漏洞影响评估

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

(受漏洞影响程度取决于合约的逻辑,具体代码审计结果可联系我们)

以太坊智能合约构造函数大小写编码错误漏洞-RadeBit瑞安全

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

以太坊智能合约构造函数大小写编码错误漏洞-RadeBit瑞安全

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

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

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

四、防护方案

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

以太坊智能合约构造函数大小写编码错误漏洞-RadeBit瑞安全