在昨日,BCSEC安全团队发现了某已经流通于多个交易所的ERC20代币存在一个高危漏洞,随后便通报给了厂商,没有马上披漏。但是今天BCSEC安全团队发现此漏洞已经被利用,而且厂商已经进行了相应的措施,于是我们决定将此漏洞详情进行披漏。
编码笔误问题
在开发者进行编码的过程中,出现笔误是非常常见的问题,有些笔误非常隐蔽,在IDE不进行提示或报错的情况下,用人眼非常难以发现,而且这种问题在以往的传统安全中就发生过不少。
2016年Chrome V8引擎因开发者笔误造成任意代码执行
由开发者笔误把>= 错误地写成了 ==造成的CloudFlare漏洞泄露海量用户信息
...
这些是在以往开发者在传统应用上由于编码笔误造成的严重漏洞,而上面的例子仅是冰山一角。
在传统应用中出现了这种漏洞的时候,常见的做法是直接发布新版本通过升级来修补漏洞。
但在区块链应用上,修复漏洞将变得异常艰难。
然而,在区块链应用漏洞难以修复的情况下,还是出现了很多非常低级的笔误问题。
LCX、YEED等ERC20代币存在可被任意关停交易的漏洞,而其根本原因竟是由于开发者将权限判断中的==写成了!=,最终导致权限判断失效。
ERC20代币FuturXe存在任意转账漏洞,其根本原因是由于开发者将可用余额判断中的<写成了>=,最终导致可有余额判断失效。
...
以上编码笔误问题都直接造成了非常严重的经济损失,而其原因仅仅是开发者将某个字符写错造成。
构造函数笔误
在关键操作的代码中,任何一个字符都必须要谨慎,而构造函数是进行非常敏感的初始化操作。
这时候若存在编码笔误会造成怎样的影响呢,我们来看下面这个案例。
MorphToken,一个具有数千万市值万的ERC20代币。
以上是MorphToken的部分代码,仔细看这段代码其实是没有问题的,但是这个合约继承了一个名为Owned的合约,而问题就出在这里,我们继续看。
乍一看,没有问题,一段短而精悍的鉴权合约。
但是我们仔细看看构造函数
function owned() public
我们再看看合约名
contract Owned
发现问题没有?合约名和构造函数大小写不一致!
这会造成什么问题?构造函数被识别为普通函数,任何人可以窃取owner权限...
这不是个例。
BCSEC团队使用内部扫描器就扫描出来50多种笔误合约,而其中可以窃取owner权限的更是有十多个。
如何预防?
使用solidity高于0.4.22的编译器,并把构造函数写为constructor。
这是solidity编译器再0.4.22新增的一个特性,可以将构造函数写为constructor避免程序员笔误。
漏洞已经被黑客利用
在昨天我们发现此漏洞的时候我们及时通报给了厂商,但厂商并没有给予回应。
我们打算等待厂商修复之后再进行披漏!
然而!就在13小时前,漏洞就已经被利用!
0x82d71f44fe03a0ecfe6765d45a871b7b9c30dd3e用户窃取了owner权限
随后此用户开始利用owner权限对自己进行发币!
而管理员的反应也非常迅速,于是他们展开了一场巅峰对决。。。
0x1ff用户就是原管理员,在原管理员发现漏洞之后火速使用了数次漏洞函数,原管理员和黑客在争夺owner权限!
最终,原管理员终于夺回了owner权限!并使用合约函数拉黑了黑客的账户。
这场对决到到此结束,我们来看看市场反应。
果不其然,跌到了历史最低!
而这位黑客已经功成身退,赚的盆满钵满了。
黑客卖了近60万个Morph ,大约价值为430个以太坊,换成人民币就是130万!
最后 ,官方也发布了公告。
总结
关于区块链的代码只要被去中心化后相要再修复是非常艰难的,所以上公链之前必须要对代码进行多方审计,而且不能放过任何一个细节。