智能合约 transferFrom 权限控制不当导致的任意盗币攻击简述

因为突发的 EDU、BAI 等智能合约漏洞导致代币被盗事件,我写了一篇相关的技术简述,这里也分享下。
更多的情报大家可以关注知识星球里的慢雾区,之前发过:-)
智能合约里的 transferFrom 是批准转账流程里的关键函数,这个由于不如 transfer 那么常用,容易被不小心忽略。这个流程最大的问题是权限问题。看代码说话:
// 批准转账上限(批准目标可以代我转账的上限)
function approve(address _spender, uint256 _value) public returns (bool success) {
allowed[msg.sender][_spender] = _value;
Approval(msg.sender, _spender, _value);
return true;
}
// 代我转账的流程
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) {
/// same as above
require(_to != 0x0);
require(balances[_from] >= _value);
require(balances[_to] + _value > balances[_to]);
uint previousBalances = 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);
return true;
}
可以看出,这个流程并没做 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] 不存在,那么值是 0,减去 _value(大于 0 时),就溢出了(溢出并不会导致中断回滚)。这就是为什么如果用了 SafeMath 就会没问题,因为 SafeMath 会抛出错误,直接中断回滚 transferFrom 函数。
整体这样看下来,EDU 和 BAI 等合约的 transferFrom 盗币事件最核心的问题是权限问题,溢出在这仅仅是个小插曲而已。
黑客与区块链系列文章:
杂谈地下黑客的匿名对抗一
5天钓到40枚以太币
以太坊生态缺陷导致的一起亿级代币盗窃大案
以太坊黑色情人节专题上线及一些补充观点
...
如果你觉得这篇文章对你有启发,可以打赏:
狗币地址:
9zdJzhm8oTLFMhzF4rFa2igJDnfoRGj8mV
-----------------
微信公众号「Lazy-Thought」
几个黑客在维护,都很懒,都想改变点什么
关注公众号:拾黑(shiheibook)了解更多
[广告]赞助链接:
四季很好,只要有你,文娱排行榜:https://www.yaopaiming.com/
让资讯触达的更精准有趣:https://www.0xu.cn/
关注网络尖刀微信公众号随时掌握互联网精彩
- 1 《求是》发表习近平总书记重要文章 7904530
- 2 销售直言不建议买35万玛莎拉蒂 7809151
- 3 警方通报老人坐门口吃橘子被打倒 7711782
- 4 明年经济工作政策取向确立这八个字 7618714
- 5 《怦然心动》导演家中死亡 其子已被捕 7523911
- 6 9天涨粉400万的“蛋神”发声 7424923
- 7 泰柬冲突急转直下 世界三个没想到 7330194
- 8 金建希被曝曾深夜激烈怒斥尹锡悦 7232177
- 9 香奈儿“购物篮”包拍出超百万天价 7142765
- 10 如何让你我的钱袋子鼓起来 7043185

余弦
