主页 > 苹果手机imtoken下载 > 以太坊智能合约漏洞详解:整数溢出攻击

以太坊智能合约漏洞详解:整数溢出攻击

苹果手机imtoken下载 2023-06-22 07:32:43

以太坊智能合约漏洞详解:整数溢出攻击

96

零时技术

2019.03.19 07:17字数2638

x01溢出攻击事件

2018年4月22日,黑客对BEC智能合约发起攻击,并取出

美的电饭煲预约煮粥会溢出吗_合约开多为什么会溢出usdt_电压力锅煮粥会溢出

BEC代币在市场上大量抛售,随后BEC大幅贬值,价值几乎为0,市场瞬间崩盘。

2018年4月25日,SMT项目方发现其交易出现异常,黑客利用其功能漏洞创建

美的电饭煲预约煮粥会溢出吗_合约开多为什么会溢出usdt_电压力锅煮粥会溢出

火币Pro立即暂停所有币种的充值和提现业务。

2018年12月27日,以太坊智能合约Fountain(FNT)出现整数溢出漏洞合约开多为什么会溢出usdt,黑客利用其函数漏洞创建

美的电饭煲预约煮粥会溢出吗_合约开多为什么会溢出usdt_电压力锅煮粥会溢出

SMT硬币。

让我们怀着沉重的心情缅怀那些一夜之间归零的代币。

0x02 Integer Overflow 整数溢出原理介绍

一般来说,由算术问题引起的整数溢出漏洞在编程语言中并不少见。 在区块链的世界里,智能合约的Solidity语言也存在整数溢出问题。 整数溢出一般分为上溢和下溢。 溢出,智能合约中存在三种类型的整数溢出:

乘法溢出

加法溢出

减法溢出

在Solidity语言中,变量支持的整型步长增加了8,从uint8到uint256,从int8到int256。 例如uint8类型只能存储0到2^8-1范围内的数字,即[0,255],uint256类型只能存储0到2^256-1范围内的数字。

为以太坊虚拟机(EVM)中的整数指定一个固定大小的数据类型,它是无符号的,这意味着以太坊虚拟机中的整数变量只能表示一定范围的数字,不能超过这个规范范围。

如果你尝试把256这个数存储在一个uint8类型中,256这个数最终会变成0,所以整数溢出的原理其实很简单。 为了说明整数溢出的原理,这里以8(uint8)位无符号整数为例,8位整数的可表示范围为[0, 255],255在内存中的存储形式如下图下图:

美的电饭煲预约煮粥会溢出吗_合约开多为什么会溢出usdt_电压力锅煮粥会溢出

8位无符号整数255在内存中占8位。 如果加1,由于进位,整体会翻转为0,最后原来的8位整数会变成0。

上图说明了智能合约中整数溢出的原理,整数下溢也是如此,比如(uint8)0 - 1 = (uint8)255。

溢出的简单演示,这里以uint256类型进行演示:

美的电饭煲预约煮粥会溢出吗_合约开多为什么会溢出usdt_电压力锅煮粥会溢出

在编辑器上编译并部署上述代码。 为了方便在这里使用:editor。

加法溢出

这里将uint256类型的max变量设置为其最大值(2**256 - 1),然后给max变量加1,导致溢出,max最终输出值为0。

美的电饭煲预约煮粥会溢出吗_合约开多为什么会溢出usdt_电压力锅煮粥会溢出

减法溢出

在这里,uint256 类型的变量 min 被设置为其最小值 (0)。 如果减去一个1,导致下溢,min最后的值会变成一个很大的值,即2**256-1。 即uin256类型的最大值。

美的电饭煲预约煮粥会溢出吗_合约开多为什么会溢出usdt_电压力锅煮粥会溢出

乘法溢出

这里将uint256类型的mul变量设置为2**255,然后将mul变量乘以2变成2**256,超过最大值导致溢出,最终结果mul值输出为0。

美的电饭煲预约煮粥会溢出吗_合约开多为什么会溢出usdt_电压力锅煮粥会溢出

通过例子可以看出,uint256取最大整数值时,溢出后直接返回0,uint256取0下溢时,直接返回2^256-1。 这是solidity中整数溢出场景的一般情况,同样的原理也适用于uint8等其他类型。

整数溢出保护

为了防止整数溢出的发生,一方面可以在运算逻辑前后进行校验,另一方面可以直接使用OpenZeppelin维护的智能合约函数库中的SafeMath来进行运算处理逻辑。

美的电饭煲预约煮粥会溢出吗_合约开多为什么会溢出usdt_电压力锅煮粥会溢出

美的电饭煲预约煮粥会溢出吗_合约开多为什么会溢出usdt_电压力锅煮粥会溢出

使用Safemath方法后合约开多为什么会溢出usdt,不再产生溢出漏洞:

美的电饭煲预约煮粥会溢出吗_合约开多为什么会溢出usdt_电压力锅煮粥会溢出

通过使用Safemath封装的加减乘运算接口,使用assert方法进行判断,可以避免溢出漏洞。

0x03 案例分析

而上面的例子介绍了原理。 下面我们将通过一个实际案例来介绍溢出漏洞是如何在生产环境中被恶意攻击的。

案例一

漏洞原理分析

BEC合约地址:0xC5d105E63711398aF9bbff092d4B6769C82F793D

etherscan 上的地址是:

存在溢出漏洞的合约代码如下:

美的电饭煲预约煮粥会溢出吗_合约开多为什么会溢出usdt_电压力锅煮粥会溢出

可以看出,在batchTransfer函数中,有如下代码uint256 amount = uint256(cnt) * _value,没有使用safemath库,直接使用了乘法运算符,整数溢出在情理之中。

变量cnt是转账地址的个数,可以通过外部用户输入_receivers来控制,_value是单个地址的转账数量,也可以直接控制。

外界可以控制_receivers和_value的值,那么我们就可以控制amount变量的值,让它产生意想不到的值,导致向上溢出。 比如cnt = _receivers.length = 2, _value = 2**255,所以amount = uint256(cnt) * _value = 2**255*2超过了uint256表示的最大值,导致溢出,最后amount = 0。

紧接着,有一个代码 require(_value > 0 && balances[msg.sender] >= amount) 检查金额; 其中balances[msg.sender]代表当前用户的余额,amount代表转出的币总数。 代码的含义是保证单个用户的转账金额大于0,且当前用户拥有的token余额大于等于本次转账的总币数,才能进行后续的转账操作。 因为amount溢出可以是一个小数或者0(这里变成0),所以很容易绕过balances[msg.sender] >= amount的校验码。 结果,产生了巨额_value(这里是2**255)的恶意转账。

实际攻击的恶意转账记录:

从转账记录可以看出,分别向两个账户转入了大笔代币。

美的电饭煲预约煮粥会溢出吗_合约开多为什么会溢出usdt_电压力锅煮粥会溢出

攻击模拟演示

为了真实模拟黑客攻击过程,下面给出一个演示。

实际操作视频链接:

下面我们在remix编辑器中编译部署BEC合约的代码,然后调用batchTransfer函数。

美的电饭煲预约煮粥会溢出吗_合约开多为什么会溢出usdt_电压力锅煮粥会溢出

转账到两个需要转账的账户:["0x14723a09acff6d2a60dcdf7aa4aff308fddc160c","0x4b0897b0513fdc7c541b6d9d7e929c4e5364d2db"]

然后转给单用户转账金额57896044618658097711785492504343953926634992332820282019728792003956564819968(2**255)

最后转出后,转出账户:0xca35b7d915458ef540ade6068dfe2f44e8fa733c代币不变,两个转入账户的余额都变得很大。

美的电饭煲预约煮粥会溢出吗_合约开多为什么会溢出usdt_电压力锅煮粥会溢出

Bug修复

正如您在代码中看到的,在语句 balances[msg.sender] = balances[msg.sender].sub(amount) 和 balances[_receivers[i]] = balances[_receivers[i]].add(_value) ,调用Safemath库中的safe函数完成加减运算,所以这里需要使用Safemath进行乘法运算,将代码uint256 amount = uint256(cnt) * _value改为uint256 amount = uint256(cnt) .mul(_value);,如图所示,使用Safemath库后,攻击转移失败。

美的电饭煲预约煮粥会溢出吗_合约开多为什么会溢出usdt_电压力锅煮粥会溢出

案例二贴片机

BEC合约地址:0x55F93985431Fc9304077687a35A1BA103dC1e081

etherscan 上的地址是:

存在溢出漏洞的合约代码如下:

美的电饭煲预约煮粥会溢出吗_合约开多为什么会溢出usdt_电压力锅煮粥会溢出

从代码中可以看出,这里的加减乘并没有使用安全处理,直接进行算术运算,而_from、_to、_value、_feeSmt都是可控的,导致if(balances[_from] < _feeSmt + _value) revert(); 这里,构造_value,_feeSmt为刚好溢出为0的值

美的电饭煲预约煮粥会溢出吗_合约开多为什么会溢出usdt_电压力锅煮粥会溢出

比如将上面的value和feeSmt相加,然后去掉最高位,结果为0,小于balances[_frome],这样不满足if条件,绕过判断。

从攻击的交易信息可以看出,黑客构造的内容:

美的电饭煲预约煮粥会溢出吗_合约开多为什么会溢出usdt_电压力锅煮粥会溢出

从上图可以看出,_value和_feeSmt之和恰好溢出为0,绕过了if条件判断,从而将value和feeSmt的代币分别转入to账户和msg.sender账户。

案例 3 FNT

FNT合约地址:0x82Cf44bE0768A3600c4BDeA58607783A3A7c51AE

etherscan 上的地址是:

该漏洞与案例一中的BEC漏洞如出一辙,存在溢出漏洞的合约代码如下:

美的电饭煲预约煮粥会溢出吗_合约开多为什么会溢出usdt_电压力锅煮粥会溢出

美的电饭煲预约煮粥会溢出吗_合约开多为什么会溢出usdt_电压力锅煮粥会溢出

从上面的代码我们可以看出receivers和amount这两个变量是可控的。 首先计算需要转账的总金额totalAmount,然后判断totalAmount大于0,msg.senders的余额大于totalAmount的值,最后将receivers和amount的钱一一转出. .

这里的溢出点是totalAmount += amounts[i]; 计算转移总额的地方。 当amount的元素相加产生overflow时,overflow可以构造成一个很小的值,比如1或者2。构造出来的amount如下:

美的电饭煲预约煮粥会溢出吗_合约开多为什么会溢出usdt_电压力锅煮粥会溢出

所以通过上面的构造,我们成功绕过了判断,最终分别向两个账户转入2个代币和115792089237316195423570985008687907853269984665640564039457584007913129639935(2*256-1)个代币。

通过攻击的交易信息,我们可以看到结果和我们的分析是一致的:

美的电饭煲预约煮粥会溢出吗_合约开多为什么会溢出usdt_电压力锅煮粥会溢出

0x04 摘要

我们在开发智能合约的时候,如果开发者不注意,只要不检查用户的输入内容,最后将输入带入执行计算,导致计算结果的数量超出了允许的范围存储它们的数据类型,然后智能合约的输入可用于防止攻击,从而导致安全漏洞。

因此,为了防止整数溢出的发生,一方面可以在算术逻辑前后进行验证,另一方面可以直接使用OpenZeppelin维护的智能合约函数库中的SafeMath来处理算术逻辑。

很多项目在合约中导入了SafeMath库,但由于开发者的粗心,导致部分计算忘记添加已经使用的safemath库,导致溢出漏洞。 因此,除了开发者自身提高安全开发意识外,还需要找专业的安全团队对合约进行全面审计。

杂志

©版权归作者所有