下一篇:区块链智能合约安全之二(重入漏洞)
transferFrom权限控制不当导致的任意盗币攻击
智能合约里的transferFrom是批准转账流程里的关键函数,这个由于不如transfer那么常用,容易被不小心忽略。这个流程最大的问题是权限问题。看代码说话:
//批准转账上限(批准目标可以代我转账的上限)
functionapprove(address_spender,uint256_value)publicreturns(boolsuccess){
allowed[msg.sender][_spender]=_value;
Approval(msg.sender,_spender,_value);
returntrue;
}
//代我转账的流程
functiontransferFrom(address_from,address_to,uint256_value)publicreturns(boolsuccess){
///sameasabove
require(_to!=0x0);
require(balances[_from]>=_value);
require(balances[_to]+_value>balances[_to]);
uintpreviousBalances=balances[_from]+balances[_to];
balances[_from]-=_value;
balances[_to]+=_value;
allowed[_from][msg.sender]-=_value;
Transfer(_from,_to,_value);
assert(balances[_from]+balances[_to]==previousBalances);
returntrue;
}
可以看出,这个流程并没做allowed[_from][msg.sender]和_value的判断,比如函数开始应该判断:
require(allowed[_from][msg.sender]>=_value);
如果allowed[_from][msg.sender]不存在,那么值是0,判断缺失,也就等于之前的approve函数形同虚设。然后,这还出现了个有趣的溢出:
allowed[_from][msg.sender]-=_value;
allowed[_from][msg.sender]= allowed[_from][msg.sender]- _value
当allowed[_from][msg.sender]不存在,那么值是0,减去_value(大于0时),就溢出了(溢出并不会导致中断回滚)。这就是为什么如果用了SafeMath就会没问题,因为SafeMath会抛出错误,直接中断回滚transferFrom函数。
整体这样看下来,EDU和BAI等合约的transferFrom盗币事件最核心的问题是权限问题,溢出在这仅仅是个小插曲而已。
网友评论