EDU&BAI任意转走账户Token事件回顾 – 作者:BUGX

*本文中涉及到的相关漏洞已报送厂商并得到修复,本文仅限技术研究与讨论,严禁用于非法用途,否则产生的一切后果自行承担。

事件背景

5月23日晚间,EDU(EduCoin)被爆出现合约漏洞,多达数十亿代币被盗。EduCoin是建立在区块链和智能合约技术基础上,面向在线教育内容分享和服务的去中心化教育平台,而EDU是基于以太坊ERC-20协议发行的项目代币,总量150亿。

在曝出合约漏洞之前,EDU的交易K线就已出现了大量抛售的现象。从5月20日午夜开始,大量EDU被人抛售,而持续的抛售带来的则是市场的进一步恐慌,EDU的价格持续走低,直到EDU的交易对被迫关停,期间累计售出的EDU超过20亿。

黑客之所以非常容易得窃取了代币,正是因为EDU的智能合约,存在一个非常大的安全漏洞。

漏洞概述

针对EDU&BAI智能合约出现的问题,BUGX团队做了一些简单分析,仅供参考:

在 transferFrom 函数中,未校验 `allowed[_from][msg.sender] >= _value` 并且函数内 `allowed[_from][msg.sender] -= _value`; 没有使用 SafeMath,导致无法抛出异常并回滚交易。目前发现有大量洗劫行为,攻击者不需要私钥即可转走你账户里所有的 EDU,并且由于合约没有 Pause 设计,导致无法止损。 

本漏洞目前被发现在EDU及BAI合约中。 

合约转账情况: 

EDU: < https://etherscan.io/token/0xa0872ee815b8dd0f6937386fd77134720d953581

BAI:< https://etherscan.io/token/0x14d9779b6585f3a7d4f768383b3cb030705dad2e

漏洞原理

合约中漏洞代码如下:

// 批准转账上限(批准目标可以代我转账的上限)
    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); // 检测被转账者余额大于_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 盗币事件最核心的问题是权限问题,溢出在这仅仅是个小插曲而已。 

本地复现

使用Remix即可简单复现。 

1 部署合约 

EDU:< https://etherscan.io/address/0xa0872ee815b8dd0f6937386fd77134720d953581#code

BAI:< https://etherscan.io/address/0x14d9779b6585f3a7d4f768383b3cb030705dad2e#code

2 执行攻击 

被转账者(使用合约创建者地址即可):0xca35b7d915458ef540ade6068dfe2f44e8fa733c 

攻击者:0x14723a09acff6d2a60dcdf7aa4aff308fddc160c 

transferFrom里输入内容并执行:”0xca35b7d915458ef540ade6068dfe2f44e8fa733c”,”0x14723a09acff6d2a60dcdf7aa4aff308fddc160c”,”3″ 

可以看到攻击者余额增加了,变为3。

134.jpg

*本文作者:BUGX-Tri0nes,转载请注明来自FreeBuf.COM

来源:freebuf.com 2018-07-09 22:21:10 by: BUGX

© 版权声明
THE END
喜欢就支持一下吧
点赞0
分享
评论 抢沙发

请登录后发表评论