尊龙凯官网入口ADLab:以太坊智能合约多个攻击案例剖析
宣布时间 2018-08-25一、使用Oraclize服务的疏忽
为了将区块链手艺应用到线下,例如将飞机延误险、数字钱币兑换等营业上链,区块链需要具有会见链外数据的能力。可是若是智能合约直接从外部服务获取数据,由于网络延迟,节点处置惩罚速率等种种缘故原由,会导致每个结点获取的数据差别,使区块链的共识机制失效。
现有的解决计划是使用第三方发送区块链的生意,生意会同步到每个节点,从而包管数据的一致性。Oraclize是一个预言机,为以太坊等区块链提供数据服务,它自力于区块链系统之外,是一其中心化的第三方。Oraclize可以提供的数据会见服务包括随机数、URL会见、IPFS等。Oraclize的架构如图所示:
Oraclize不是链上直接可以挪用的函数,而是一个链外的实体。为了抓取外部数据,以太坊智能合约需要发送一个盘问请求给Oraclize,当Oraclize监听到链上有相关请求时,连忙对互联网上的资源提倡会见,然后挪用合约中的回调函数__callback将盘问效果返回区块链。
例如,用美元兑换以太币的智能合约的数据盘问语句如下:
监听到请求后,Oraclize会会见URL获得盘问效果,然后挪用__callback的函数,Oraclize返回的数据通过__callback函数参数传回智能合约。上图中函数挪用的参数[3]中的“3334312e3533”即为其时的汇率:1ETH = $341.53,随后智能合约会凭证这个盘问效果举行后续的逻辑处置惩罚。
1、攻击案例:SIGMA (0x03AF37073258B08FfFF303e9E07E8a0B7bfc4fd9)
SIGMA合约使用了Oraclize服务盘问汇率。该合约的__callback回调函数如下:
由于__callback函数中保存整数溢出,导致owner的代币余额被下溢成一个很大的值,导致代币增发。从代币份额排名可以看出攻击者的账户地址为0x2ef045a75b967054791c23ab93fbc52cc0a35c80,而该地址并不是建设合约的账户地址(0xC7e92D8997359863a8F15FE87C0812D7A3a8F770)。
跟踪Transactions,发明0xC7e92D8997359863a8F15FE87C0812D7A3a8F770调transfer_ownership将合约的owner设置为0x2ef045a75b967054791c23ab93fbc52cc0a35c80。
针对这个误差是否使用SafeMath就可以解决了呢?谜底是否定的。在Oraclize挪用__callback之前,有用户对盘问函数的挪用,并且这个挪用破费以太币。
使用SafeMath的情形下,爆发溢出的事务会回滚,但本例中能够回滚的只有Oraclize对__callback函数挪用的事务,而之前用户破费以太币爆发的事务则无法回滚。这个征象的基础缘故原由是Oraclize是一个自力的实体,导致逻辑上应该完整的一个操作被支解成了两个事务。因此,通过Oraclize与链下数据交互时只能越发小心,代码编写需要越发审慎。
二、庞氏代币合约误差
以太坊智能合约中混杂进了不少庞氏圈套合约,他们向投资者允许,若是你向某合约投资一笔以太坊,它就会以一个高回报率回赠你更多的以太币,然而高回报只能从后续的投资者那里源源一直地吸收资金以反响给前面的投资者。
1、攻击案例:ETHX( 0x1c98eea5fe5e15d77feeabc0dfcfad32314fd481)
ETHX是一个典范的庞氏代币合约。该合约可以看成虚拟币生意所,但只有ETH和ETHX (ERC20 token)生意对,每次生意,都有5%的token分派给整个平台的已有的token持有者,因此token持有者在持币时代,将会直接赚取新购置者和旧抛售者的手续费。从ETHX合约代码可以看出,该合约对transferFrom函数举行了扩展,transferFrom函数首先举行allowance限额判断,然后挪用了自界说的transferTokens函数来完成转账。
在transferTokens函数中,当to账户地址不即是合约地址,由于事先对from账户额度举行了清静检查,因以后面临from账户的balance运算不会爆发溢出。
当to账户地址即是合约地址时,则挪用sell函数,sell函数中由于代码编写失误,过失的将from写成msg.sender,对msg.sender的额度举行了减法操作,而在减法操作前没有举行清静检查,因此保存溢出误差。
为了完成对这个溢出误差的攻击,攻击者需要2个账户A、B,其中A账户代币余额不为0,B账户代币为0。
? A账户挪用approve给B授权一部分转账额度,假设授权额度为1;
? B账户挪用transferFrom,从A账户转1单位代币到智能合约;transferFrom挪用sell函数时触发整数溢出,即0-1=2^255。B账户在余额为0的情形下获得了最大额度的token。
在ETHX合约攻击链中,攻击者使用了两个账户地址,划分为:
0x423b1404f51a2cdae57e597181da0a4ca4492f30
0x17a6e289e16b788505903cc7cf966f5e33dd1b94
首先,0x17a6e289e16b788505903cc7cf966f5e33dd1b94挪用approve给0x423b1404f51a2cdae57e597181da0a4ca4492f30授权转账额度,参数value=1。
然后,0x423b1404f51a2cdae57e597181da0a4ca4492f30挪用transferFrom要领,从账户0x17a6e289e16b788505903cc7cf966f5e33dd1b94向ETHX合约地址0x1c98eea5fe5e15d77feeabc0dfcfad32314fd481 转移1个Token。
挪用前,balance(0x423b1404f51a2cdae57e597181da0a4ca4492f30)=0。挪用后,溢出后balance(0x423b1404f51a2cdae57e597181da0a4ca4492f30)=2^255。
监控平台显示已经被攻击的同类代币合约如下表:
三、SafeMath使用不当
以太坊虚拟机EVM界说无符号整数为uint256,可以体现一个256位的大整数,但并没有提供溢出的检测机制。OpenZeppline是一个第三方智能合约库,实现了一套SafeMath库来检测溢出。其代码如下:
SafeMath使用内建的require或assert来检查运算是否爆发溢出,若是爆发了溢出,require和assert中包括的代码会使该事务回滚。但有些开发者不可完全明确SafeMath模版代码,导致合约代码中仍然保存误差。
1、攻击案例:UCN (0x6EF5B9ae723Fe059Cac71aD620495575d19dAc42)
UCN(http://www.saveunicoins.com/Unicorn/index.html)是一个智能合约DApp应用。合约代码在SafeMath库中注释assert语句,因此SafeMath函数等同于直接举行算术运算,没有任何清静检查。并且在transferFrom函数中,注释中声明sub函数是清静的,不知道这是开发职员的疏忽照旧居心留下的后门。
由于sub函数等同于算术运算,balances[_from] = balances[_from].sub(_value);
保存整数下溢误差,可以使得账户余额酿成一个极大值。
2、攻击案例:EMVC(0xd3F5056D9a112cA81B0e6f9f47F3285AA44c6AAA)
EMVC(http://crypto7.biz/)合约代码在SafeMath库中使用了一个自界说的assert来取代内建的assert。在assert函数中,若是参数assertion为false则直接return,并没有举行异常处置惩罚。因此SafeMath函数等同于直接举行算术运算,没有任何清静检查。
攻击者可以使用transfer函数设置恣意账户余额为恣意值。
四、总结
当智能合约要实现更多功效时,代码会响应变得越发重大,与ERC20标准代码的差别也越来越大,因而潜在的误差面目越发多样。为了包管智能合约的清静,除遵照清静开发原则、凭证“Check Lists”举行基线检查外,还需要实验更深入详尽的审计。


京公网安备11010802024551号