本文需要了解一下知识点
在Solidity语言当中,没有权限修饰符进行修饰的函数是默认可以被所有人调用的。
在Solidity语言的智能合约中,有个内置的函数名为selfdestruct,官方的解释为"destroy current contract
and send funds to someone",通俗解释就是销毁当前合约并把当前合约中的余额发送到某个地址。
通过上面提到的知识不难想到,两者结合的话危害将是巨大的。
可能有人会问,谁会把敏感操作放开权限给任意人用?
这就涉及到一个概率学问题,在函数默认就为任何人可调用的情况下,就一定难免有人忽略,即使这是一个非常低级的错误。
PS:事实上历史上就发生过,而且是发生在一个使用者众多的智能合约上——parity多签名钱包合约漏洞冻结价值高达上亿美金的以太币。
我们先来看一个案例(一个具有上千万市值的ERC20 Token):
可以看到destroycontract函数就没有任何权限修饰符,在进行selfdestruct的时候也没有进行调用者判断。
若被人恶意调用此函数的话,那么就会导致此合约被瞬间销毁,而且合约内的余额也将全部被攻击者洗劫走。
然而攻击者只需要在Geth console中敲如下几个简单的命令就可以完成。
Exploit:
> z***tAbi = [{"constant":true,"inputs":[],"name":"name",......,"name":"Approval","type":"event"}]
> z***tInterface = eth.contract(z***tAbi)
> publishedzxxxttAddr = 0xb5c0e43a6330b9e******57ea24d70269ae4652e
> z***t = z***tInterface.at(publishedZ***ttAddr)
>z***t.destroycontract(0xb5c0e43a6330b9e******57ea24d70269ae4652e)
本地模拟复现如下:
可以看到,在执行销毁操作后所有的方法都无法调用了。
除了未鉴权的合约自毁以外,在别的敏感操作上也会有同样的问题。
例如:
1.未鉴权的合约所有人转移
2.未鉴权的初始化
3....
理论上一切有敏感操作的函数都会面临这个问题。
经过BCSEC团队调查,发现有接近30个合约存在此问题。
其中有一个合约疑似已经被恶意销毁并窃取账户余额。
可以看到,此合约是由0x06用户创建,最后一笔交易是由0xea用户执行。
我们再来看看0xea用户执行的操作
可以看到用户调用了destroykill函数,致使合约被销毁并使合约内的0.02个以太币发送到自己的地址。
我们再来看看destroykill函数详情
看函数代码,似乎作者已经进行了权限判断,这里用了isOwner函数,但是还是被0xea销毁合约了,这里有三种可能。
合约作者自己把owner设置为0xea用户了
0xea通过漏洞使owner变为了自己的地址
isOwner函数验证不严谨
区块链具有可追溯性,这里其实我们不用一一判断,去看0xea执行过的操作就可以知道事情的来龙去脉。
这是0xea进行过的两笔交易,第一笔已经看过了,我们直接看第二笔。
0xea用户执行了Lottery函数,来看看Lottery函数函数的内容吧。
这是更改owner的函数,居然也是没有任何鉴权...
两处未鉴权结合便有了0xea用户的以上操作。
更多精彩内容请关注我们的官方网站https://bcsec.org/