攻击描述
- 被黑目标:BeautyChain
- 事件描述:黑客利用数据溢出攻击 BeautyChain 智能合约,成功将 BEC 代币转入两个地址,导致市场上大量抛售 BEC,数字货币价值几乎为零, 给 BEC 市场带来了毁灭性的打击。
- 损失金额:代币归零
- 攻击方式:整数溢出攻击
合约开发者使用了 SafeMath
库,但是使用使用的时候却没有严格使用该库。
合约描述
- 合约地址: 0xC5d105E63711398aF9bbff092d4B6769C82F793D
- 黑客地址:
- 0xb4d30cac5124b46c2df0cf3e3e1be05f42119033
- 0x0e823fFE018727585EaF5Bc769Fa80472F76C3d7
- 攻击交易: https://etherscan.io/tx/0xad89ff16fd1ebe3a0a7cf4ed282302c06626c1af33221ebe0d3a470aba4a660f
- 合约代码: https://etherscan.io/token/0xc5d105e63711398af9bbff092d4b6769c82f793d#code
攻击过程技术分析
核心代码如下:
function batchTransfer(address[] _receivers, uint256 _value) public whenNotPaused returns (bool) {
uint cnt = _receivers.length;
uint256 amount = uint256(cnt) * _value; // 这里没有使用 SafeMath
require(cnt > 0 && cnt <= 20);
require(_value > 0 && balances[msg.sender] >= amount);
balances[msg.sender] = balances[msg.sender].sub(amount); // 使用 SafeMath 减去 amount
for (uint i = 0; i < cnt; i++) {
balances[_receivers[i]] = balances[_receivers[i]].add(_value);
Transfer(msg.sender, _receivers[i], _value);
}
return true;
}
这里 amount = uint256(cnt) * _value
没有使用 SafeMath,只需要把 amount 值设为零即可。后面虽然使用 SafeMath 减去 amount,但是 amount 为零,还是可以通过检查的。
攻击者传入两个地址,value 使用 2**256
作为转账的值,2**256 * 2
刚好等于零。amount=0,绕过了require(_value > 0 && balances[msg.sender] >= amount);
异常检查语句。
下面是测试的演示。
// SPDX-License-Identifier: MIT
pragma solidity ^0.4.19;
contract BECTest {
uint256 _value = 2**255;
function mulTest() public constant returns (uint) {
uint256 amount = 2 * _value;
return amount;
}
}
修复方式
严格使用 SafeMath 即可,合约的开发者是有防范意识的,所以引入了 SafeMath,但是计算的时候没有严格的使用。
反思
认真对待自己的代码,严格按照规范编程。