智能合约攻击分析之SafeMath使用不当
摘要: 在编写智能合约的时候需要注意的一个主要的安全特性:防止溢出和下溢。为了防止这些情况,OpenZeppelin建立了一个叫做SafeMath的库(library),默认情况下可以防止这些问题。
智能合约安全咨询公司 曲速未来 提醒:在编写智能合约的时候需要注意的一个主要的安全特性:防止溢出和下溢。为了防止这些情况,OpenZeppelin建立了一个叫做SafeMath的库(library),默认情况下可以防止这些问题。
什么是溢出(overflow)?
假设我们有一个uint8, 只能存储8 bit数据。这意味着我们能存储的最大数字就是二进制11111111(或者说十进制的2^8-1 =255).
来看看下面的代码。最后 number 将会是什么值?
在这个例子中,我们导致了溢出—虽然我们加了1,但是number出乎意料地等于0了。
下溢(underflow)也类似,如果你从一个等于0的uint8减去1, 它将变成255 (因为uint是无符号的,其不能等于负数)。
使用 SafeMath
不过在我们使用之前……什么叫做库?
一个库是Solidity中一种特殊的合约。其中一个有用的功能是给原始数据类型增加一些方法。
比如,使用SafeMath库的时候,我们将使用using SafeMath for uint256这样的语法。SafeMath库有四个方法—add,sub,mul,以及 div。
以太坊虚拟机EVM定义无符号整数为uint256,可以表示一个256位的大整数,但并没有提供溢出的检测机制。OpenZeppline是一个第三方智能合约库,实现了一套SafeMath库来检测溢出。其代码如下:
SafeMath使用内建的require或assert来检查运算是否发生溢出,如果发生了溢出,require和assert中包含的代码会使该事务回滚。但有些开发者不能完全理解SafeMath模版代码,导致合约代码中仍然存在漏洞。
1.攻击案例:UCN (0x6EF5B9ae723Fe059Cac71aD620495575d19dAc42)
UCN是一个智能合约DApp应用。合约代码在SafeMath库中注释assert语句,因此SafeMath函数等同于直接进行算术运算,没有任何安全检查。并且在transferFrom函数中,注释中声明sub函数是安全的,不知道这是开发人员的疏忽还是故意留下的后门。
由于sub函数等同于算术运算,balances[_from] = balances[_from].sub(_value); 存在整数下溢漏洞,可以使得账户余额变成一个极大值。
2.攻击案例:EMVC(0xd3F5056D9a112cA81B0e6f9f47F3285AA44c6AAA)
EMVC合约代码在SafeMath库中使用了一个自定义的assert来代替内建的assert。在assert函数中,如果参数assertion为false则直接return,并没有进行异常处理。因此SafeMath函数等同于直接进行算术运算,没有任何安全检查。
攻击者可以使用transfer函数设置任意账户余额为任意值。
总结
智能合约安全咨询公司 曲速未来 提醒:当智能合约要实现更多功能时,代码会相应变得更加复杂,与ERC20标准代码的差异也越来越大,因而潜在的漏洞面貌更加多样。为了保证智能合约的安全,除遵循安全开发原则、按照“Check Lists”进行基线检查外,还需要实施更深入细致的审计。
本文内容由 曲速未来 (WarpFuture.com) 安全咨询公司独家编译,转载请注明。 曲速未来提供包括主链安全、交易所安全、交易所钱包安全、DAPP开发安全、智能合约开发安全等相关区块链安全咨询服务。
(作者:区块链安全档案,内容来自链得得内容开放平台“得得号”;本文仅代表作者观点,不代表链得得官方立场)
评论(0)
Oh! no
您是否确认要删除该条评论吗?