几个智能合约漏洞分析
Created At :
Views 👀 :
1、CVE-2018-11810
超额定向分配相关合约源码
漏洞点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| function allocate(address _address, uint256 _amount, uint8 _type) public onlyOwner returns (bool success) { // one allocations by address require(allocations[_address] == 0); if (_type == 0) { // advisor // check allocated amount require(advisorsAllocatedAmount + _amount <= ADVISORS_AMOUNT); // increase allocated amount advisorsAllocatedAmount += _amount; // mark address as advisor advisors[_address] = true; } else if (_type == 1) { // founder // check allocated amount require(foundersAllocatedAmount + _amount <= FOUNDERS_AMOUNT); // increase allocated amount foundersAllocatedAmount += _amount; // mark address as founder founders[_address] = true; } else { // check allocated amount require(holdersAllocatedAmount + _amount <= HOLDERS_AMOUNT + RESERVE_AMOUNT); // increase allocated amount holdersAllocatedAmount += _amount; }
|
1 2 3 4 5 6 7 8 9 10 11 12
| // 5% for advisors uint256 constant ADVISORS_AMOUNT = 5 * onePercent; // 15% for founders uint256 constant FOUNDERS_AMOUNT = 15 * onePercent; // 60% sold in pre-sale uint256 constant HOLDERS_AMOUNT = 60 * onePercent; // 20% reserve uint256 constant RESERVE_AMOUNT = 20 * onePercent; // ADVISORS_AMOUNT + FOUNDERS_AMOUNT + HOLDERS_AMOUNT +RESERVE_AMOUNT uint256 constant INITIAL_AMOUNT = 100 * onePercent; // 20% for holder bonus uint256 constant BONUS_AMOUNT = 20 * onePercent;
|
- 分别对应上述漏洞点中的三个require,主要的发生位置即为转账数额。allocate中_amount是可控的,同时为uint256,那么向上溢出可以使得和为0,满足require条件,但下面的加钱操作会使得数额超出限制。
- 以5%的为例,使用两个账户测试,首先计算最大的数额
- 可以看到当超出这个范围时就会失败
- 将传入的金额为2^256 - 最大规定数额,那么溢出后为0,满足条件
2、CVE-2018-11809
超额铸币相关合约源码
1 2 3 4 5 6 7 8 9
| function mint(address _holder, uint256 _value) external icoOnly { require(_holder != address(0)); require(_value != 0); require(totalSupply + _value <= tokenLimit);
balances[_holder] += _value; totalSupply += _value; Transfer(0x0, _holder, _value); }
|
3、CVE-2018-11687
下溢增持相关合约源码
1 2 3 4 5 6 7
| function distributeBTR(address[] addresses) onlyOwner { for (uint i = 0; i < addresses.length; i++) { balances[owner] -= 2000 * 10**8; balances[addresses[i]] += 2000 * 10**8; Transfer(owner, addresses[i], 2000 * 10**8); } }
|
- 通过BitcoinRed函数中balances (owner)限制上限,执行多次balances(addresses)的加操作后,可以整型上溢出,同时因为没有判断Owner的账户是否有足够的余额,所以导致了减法的整型下溢出.
4、CVE-2018-11811
高卖低收相关合约源码
1 2 3 4 5 6
| function sell(uint256 amount) { require(this.balance >= amount * sellPrice); _transfer(msg.sender, this, amount); msg.sender.transfer(amount * sellPrice); } }
|
- 漏洞描述:sellPrice被修改为精心构造的大数后,可导致amount * sellPrice的结果大于整数变量(uint256)最大值,发生整数溢出,从而变为一个极小值甚至归零
1 2 3 4 5 6 7 8 9 10
| function setPrices(uint256 newSellPrice, uint256 newBuyPrice) onlyOwner { sellPrice = newSellPrice; buyPrice = newBuyPrice; }
/// @notice Buy tokens from contract by sending ether function buy() payable { uint amount = msg.value / buyPrice; // calculates the amount _transfer(this, msg.sender, amount); // makes the transfers }
|
- 根据以上两个函数setPrices与buy修改sellPrice的值,造成溢出.
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 1259742453@qq.com