一、构造函数引发问题

我们知道在大多数太坊合约均需要一个Owner来控制合约的正常运行,无论是涉及token的转账还是用于控制某些函数的启动。而许多合约中Owner的权限是非常大的,如果Owner的安全性得不到保障,那么作恶人员能够很轻易拿到合约的最高权限并轻易作恶,其带来的后果是非常严重的。

第一个问题也是最简单却是危害性最大的。

经常写合约代码的读者应该知道,早起的合约构造函数是使用合约名。例如:

contract Owned {
  address public owner;
  function Owned() {
    owner = msg.sender;
  }
}

当合约部署完毕后其构造函数自动执行,并赋值owner新的地址。而以太坊solidity在0.4.22后引入了新的构造函数声明形式constructor(),该函数引入的目的是避免编程人员在编写构造函数时的命名错误(这个问题我在前文也提到过,确实很伤-------)。然而,由于用户编写函数时习惯性的使用function进行声明,从而导致构造函数constructor的使用引入新的漏洞。

正确的构造函数形式:constructor() public { }

错误的构造函数形式:function constructor() public { }

在Solidity0.4.22版本后,合约的constructor()函数才被视为构造函数的形式,并且直到下一版本才会对function constructor()的形式给出警告(注意:这里仅仅是警告,不是错误)。如果是使用Solidity0.4.23之前的版本,编译器把function constructor()作为普通函数进行编译,认为是正确的普通函数。

下面我们来看一个例子:

在该例子中,编译器并没有因函数名不对而报错,反而一切正常。然而当我们仔细观察函数时我们就能发现上述的问题——即我们的构造函数多写了一个function。而这也会导致该函数无法起到构造函数的作用从而变成一个普通函数。

下面我们做一个简单的测试:

首先我们在本地部署合约:

当合约完成后调用Owner发现该owenr的address为0x000000。所以该函数根本没有起到作用。

而随着Solidity版本的更新,该问题也逐渐得到了解决,当我们使用最新版本的Solidity时,我们能发现:

此处使用的最新版本,它不通过编译。所以当现在合约编写者再编写合约的时候,应该多多考虑使用新版本,能够避免很多灾难性的失误。

1.新的constructor使用方法为,前面无function声明:

2.Remix-ide等编译器会对constructor的错误使用产生警告,开发者千万不要忽略编译器告警,推荐更改源码,消除所有编译器警告。

二、CVE-2018-11329

首先该漏洞展示的就是这个被人攻击的放置类游戏的智能合约,游戏名为Ether Cartel。与要求玩家孵化并且售卖虾子、之后提高产量再交易虾卵以换取以太币的的Ether Shrimp Farm应用类似,Ether Cartel也是相同的思路,只不过场景换成了某种非法物品交易。你所拥有的量越多,你生产的物品越多(一比一的生产比率)。收集更多的物品就可以加倍生产速度”。

在图中我们能够看出该合约误写了一个普通函数用于改变ceoAddress变量,而这个危害是非常大的。

当我更好账户的时候,我们可以任意调用DrugDealer()函数,并改变合约的owenr地址。

该漏洞为受ceoAnyone漏洞影响的放置游戏智能合约。Ether Cartel在UTC时间2018年5月18日17点14分56秒部署到主网,不幸的是一小时十一分钟之后即被攻破。存在漏洞的代码在18到20行:可被人以调用方调用的DrugDealer()函数,允许调用者修改收益地址——ceoAddress。

而后拿到了权限后,攻击者能够更进一步的调用其余函数,例如:

即当调用SellDrugs函数时会将fee转入ceoAddress账户,所以当该账户被恶意篡改后,该转账金额就会被窃取。同样下面的函数类似。

三、CVE-2018-10705

本章介绍CVE-2018-10705。该CVE同样是由于Owner没有进行严格把关从而产生的漏洞。审计该代码后发现,该合约中存在任意setowner函数,使得合约任意用户可以随意改变合约的owenr,并达到作恶的目的。

/**
 *Submitted for verification at Etherscan.io on 2018-01-17
*/

pragma solidity ^0.4.19;
点击收藏 | 0 关注 | 1
  • 动动手指,沙发就是你的了!
登录 后跟帖