智能合约审计-整数溢出
2020年1月15日 星期三, 发表于 合肥
如果你对本文有任何的建议或者疑问, 可以在 这里给我提 Issues, 谢谢! :)
描述:变量在参与运算的过程中,运算结果超出了变量类型所能表示的范围,导致实际存储的计算结果出错
核心问题:非预期的整数溢出将导致智能合约运行出错,影响合约的可靠性和安全性
基础知识
整数溢出的分类
整数上溢
整数下溢
整数的分类
有符号数(int)
无符号数(uint)
Solidity中的整数类型
int8/int16/int24/…/int256(int8表示-127~127)
uint8/uint16/uint24/…/uint256(uint8表示0~255)
漏洞合约分析
pragma solidity ^0.4.24;
contract IntOverflow{
function addNumber(uint a, uint b) public constant returns (uint){
uint c;
c = a+b;
return c;
}
}
漏洞点:由于这里a、b的数值类型为uint256,a、b的最大值为2^256-1,当超过这个最大值即回到起点0从新开始,所以输出c值存在整数溢出
BTCR下溢增持漏洞分析
function distributeBTR(address[] address) onlyOwner {
for (uint i = 0; i < addresses.length; i++){
balances[owner] -= 2000 * 10**8;
balances[address[i]] += 2000 * 10**8;
Transfer(owner, addresses[i], 2000 * 10**8);
}
}
漏洞点:通过在distributeBTR函数中调用onlyOwner管理员向指定的用户列表地址进行批量打款,这里就存在一个减法下溢漏洞,当balances[owner]小于2000 * 10**8的时候,这个时候balances[owner]就为负数,但是在uint数的表示范围之内,balances[owner]值就是一个超级大的数,管理员可以通过这个漏洞对自己的balances进行增持。
整数溢出分析
-
可能产生溢出的操作:加(+)、减(-)、乘(x)
-
操作数由攻击者可控(函数参数)
-
上下文末对高危操作数进行有效校验
-
ERC20重点关注balanceOf[]、 allownce[]、 toitalBalance、 totalSupply
-
溢出成功不代表一定有危害
漏洞预防
- 有效的上下文校验
require()/assert()/revert()
- 使用SafeMath
直接调用SafeMath函数
using safeMath for uint256
SafeMath库
pragma solidity ^0.4.24;
library SafeMath {
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b);
return c;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
require(b > 0);
uint256 c = a / b;
return c;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
require(b <= a);
uint256 c = a - b;
return c;
}
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a);
return c;
}
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
require(b != 0);
return a % b;
}
}