一文读懂智能合约漏洞

2019-06-18  本文已影响0人  Dipperin

智能合约是区块链的核心技术之一,是多方参与场景中的共识规则,更是智能合约是价值传递的中枢。之所以区块链出现以后安全问题变得前所未有的重要,是因为智能合约实现的是一种价值传递,区块链上的每一个数字都是价值,每个漏洞导致的数字变化,其背后就是巨额的价值损失。

2016年6月The DAO安全漏洞,导致5000万美元的损失 2017年7月Parity多签名钱包两次安全漏洞,分别导致3000万美元、1.52亿美元的损失。 2018年4月BEC代币被盗事件,由于一行代码的安全漏洞引发其9亿美元市值几乎归零。

1、美链BEC合约漏洞

BEC漏洞实质上是一个算法上下溢出漏洞。该漏洞的原理在于,当合约提供提款或是转账功能时,一般会对地址的余额做操作,如果余额操作没用SafeMath则攻击者可以经过巧妙设计将转账的扣款金额弄成0,而转出金额弄成很大的数值,导致合约凭空产生很多token或用户凭空从合约中提出很多余额。

由此可见不止合约中的计算,程序中的所有计算都需要关心上下溢出问题,如果发生溢出漏洞则会产生很大的损失。

2、假充值漏洞

在用户进行转账时,一些合约的transfer函数对转账发起人(msg.sender)的余额检查用的是if判断方式,而这种温和的判断方式在transfer这类敏感函数场景中并非一种严谨的编码方式,而这种不严谨的编码方式是一种安全缺陷,这种安全缺陷可能会导致特殊场景下的安全问题。攻击者可以利用存在该缺陷的合约向中心化交易所、钱包等服务平台发起充值操作,若交易所仅判断如TxReceiptStatus是success,则就有可能以为充值成功,产生“假充值”“假交易”。

这种问题在于交易所的代码判断需要更加严谨,不止是要判断状态是否正确,还要判断这笔转账确实是到账了的。当然合约代码在这种问题的判断中也需要尽量避免使用if这种温和的判断方式,而应该直接用assert、require这种语句让条件不成立的情况下结果状态不为Success。

3、TheDAO事件

TheDAO事件本质上是由重入漏洞引起的。重入攻击流程如下:

1. 一个聪明的合同跟踪一些外部地址的平衡,并允许用户通过其公共资金检索withdraw(  )功能。

2. 一个恶意的智能合同使用withdraw(  )函数检索其全部余额。

3. 在更新恶意合同的余额之前,受害者合同执行call.value(amount)(  )低级别函数将以太网发送给恶意合同。

4. 该恶意合同有一个支付fallback(  )接受资金的功能,然后回调到受害者合同的withdraw(  )功能。

5. 第二次执行会触发资金转移:请记住,恶意合同的余额尚未从首次提款中更新。结果,恶意合同第二次成功退出了全部余额。

其中关键点在于,用户提款时,TheDAO调用了call.value(amount)(  )方法将金额发给调用者,问题就在于:如果调用者是个合约地址,该方法就会触发合约的一个回调函数,如果这个调用者合约是个坏合约,它就可以再次触发提款调用,以此递归导致大量金额从合约中提走。详解如下图

因此将call.value(amount)(  )改成sender.send(amount),就能避免该重入攻击,但对于DAO事件已于事无补了,因此代码安全审计非常重要。

上一篇下一篇

猜你喜欢

热点阅读