宝运莱官方网站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号