注意!Owner权限被盗——低级错误不容忽视
摘要: 开发者书写合约敏感函数(如构造函数、回调函数)时,应严格遵循官方命名要求,并重视编译器提出的警告。同时,合约在发布到主链前,开发者应在官方提供的测试网络上进行充分验证,从多角度分析合约代码,找出那些容易忽略的问题。
问题描述
以太坊Solidity 0.4.22版本在更新后,引入一种新的构造函数声明形式:constructor()public {},通过这种写法,可以避免在合约开发过程中误将构造函数名写错,使得其变为普通函数。因此,任何人在合约开发过程中,均可以调用这个函数,并更改owner的值,导致合约管理权限被盗用。
经过一些平台的自动化工具检测,准确定位到了错误代码的位置,并高亮显示。而在验证结果中,该错误的类别为 “name"(命名问题),具体内容是避免使用 ”function constructor()“ 的函数形式。
但经过分析区块链智能合约时发现,有开发者对constructor函数的使用存在问题。即,新的构造函数在给合约开发者带来便利的同时,如果合约开发者使用不当会存在一定的隐患,严重时甚至会给项目方及Token持有者带来利益上的损害。
owned合约的constructor()函数,即构造函数,将合约创建者地址赋予owner,用于后续的身份验证。然而,由于用户编写函数时习惯性的使用function进行声明,将constructor() 误写成了 functionconstructor(),从而导致构造函数constructor的使用引入新的漏洞。
注:msg.sender 为当前操作账户地址、owner为合约管理者地址
由于 functionconstructor()不是构造函数的声明形式,这里相当于声明了一个函数名为constructor的普通函数,可被执行多次;而constructor函数的可见性修饰符为public,可被其他账户地址调用并修改owner的值,盗用合约管理权限。
正确的构造函数形式:constructor() public { };
错误的构造函数形式:function constructor() public { };
以下通过Ropsten测试链对该问题进行了进一步的验证:
先使用remix编译部署测试合约Test,合约代码如下:
可以看到,刚部署合约后合约的owner为0地址,因为并没有构造函数对其进行赋值。
现在使用Remix调用constructor函数,发现交易失败,分析后发现data字段不是constructor的函数签名:
更换另一个版本的solidity编译器,执行constructor函数,发现owner被更改,说明该漏洞存在:
对该漏洞进行分析,其可能导致的后果如下:
1.合约可被普通用户窃取owner权限;
2.目前很多ERC20代币部署的时候将所有代币发放到owner账户中,如果出现此漏洞,可导致用户无限增发代币;
以及更多取决于owner权限的严重后果(也许就像灭霸打一个响指,代币灰飞烟灭?)。
Owner权限过大存在的安全隐患:
Owner是Solidity语言中对智能合约开发者的称呼,owner的能力犹如集齐6颗无限宝石的灭霸,属于超级权限。如果超级权限被盗可存在如下安全隐患:
1.随时冻结代币转账;
2.任意铸造发行新的代币;
3.销毁任意账户内的代币;
4.额外增发代币;
5.停止整套交易系统运行;
如此强大的权限一旦被黑客窃取,相当于从灭霸手上抢到了无限拳套,黑客可以对依赖智能合约交易的代币为所欲为,无论是冻结,增发,还是自毁,只需要调用合约中一个函数就可轻松实现,进而操纵整个代币的价值。而与之相关的代币也必将遭受冲击,后果不堪设想。
该如何避免这些将会导致的风险?
既然合约开发者可能会存在使用constructor函数不当,那么作为项目方应该如何去防范后期可能造成的风险呢?在此提出两种方法:
1.新的constructor使用方法为,前面无function声明:
2.Remix-ide等编译器会对constructor的错误使用产生警告,开发者千万不要忽略编译器告警,推荐更改源码,消除所有编译器警告。
再次提醒,开发者书写合约敏感函数(如构造函数、回调函数)时,应严格遵循官方命名要求,并重视编译器提出的警告。同时,合约在发布到主链前,开发者应在官方提供的测试网络上进行充分验证,从多角度分析合约代码,找出那些容易忽略的问题,同时,项目方在合约编写完成后,应当寻求有质量保证的智能合约安全审计团队进行合约安全审查,保证合约的安全性和功能准确性,希望大家能引起足够重视,并且做到防患于未然。
评论(0)
Oh! no
您是否确认要删除该条评论吗?