从一道CTF题折射出的智能合约安全问题

区块链安全档案
区块链安全档案 机构得得号

Aug 09, 2018 隶属于曲速未来安全区,安全问题深度分析、一手威胁情报披露

摘要: belluminarbank 是俄罗斯战队在 WCTF 上出的一道 EVM 题目,其中用到了很多 ETH 中经典漏洞。这道题的题目是一个存储交易类合约,用户可以通过给合约发送 ether 实现将 ether 存储在合约中的目的。攻击者的目标就是将存储在这个合约里的所有 ether 全部取走。

belluminarbank 是俄罗斯战队在 WCTF 上出的一道 EVM 题目,其中用到了很多 ETH 中经典的漏洞。虽然难度都不是很大,但是如果对 EVM 相关特性不了解的话还是有一定难度的,我们就来介绍一下ETH 智能合约中的安全问题。

这道题的题目是一个存储交易类合约,用户可以通过给合约发送 ether 实现将 ether 存储在合约中的目的。攻击者的目标就是将存储在这个合约里的所有 ether 全部取走。

我们不讲这个WCTF的题目,主要是了解智能合约中的安全问题有哪些,危害多大;

就以太坊智能合约的安全漏洞。新加坡国立大学的Loi Luu提出了现在的智能合约存在的几种安全漏洞。然而,由于智能合约目前还只是初级阶段,相信各种安全问题会不断的发现。

重入漏洞:

也被称为或与空竞争,递归调用漏洞,未知调用等。

菲尔戴安说过:这种漏洞在很多时候被很多不同的人忽略:审阅者倾向于一次一个地审查函数,并且假定保护子例程的调用将安全并按预期运行。

重入攻击介绍

1.重入攻击,可能是最着名的以太坊漏洞;第一次被发现时,每个人都感到惊讶。

2.它在数百万美元的抢劫案中首次亮相,导致了以太坊的分叉。

3.当初始执行完成之前,外部合同调用被允许对调用合同进行新的调用时,就会发生重新进入。

4.对于函数来说,这意味着合同状态可能会在执行过程中因为调用不可信合同或使用具有外部地址的低级函数而发生变化。

在以太坊中,当一个合约调用另一个合约的时候,当前的操作就要等到调用结束之后才会继续。这时,如果被调用者需要使用调用者当前所处的状态,那么这就产生了问题。

著名的DAO攻击事件就是因为这个漏洞而发生的。

示例

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

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

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

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

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

以下函数包含易受重⼊攻击影响的函数。当低级别call()函数向msg.sender地址发送ether时,它变得易受攻击; 如果地址是智能合约,则付款将触发其备⽤功能以及剩余的交易⽓体:

交易顺序依赖合约:

交易顺序依赖就是智能合约的执行随着当前交易处理的顺序不同而产生差异。例如,有两个交易T[1]和T[2],两个区块链状态S[1]和S[2],并且S[1]状态处理完交易T[2]后才能转化为状态S[2]。那么,如果矿工先处理交易T[1],交易T[1]调用的就是S[1]状态下的智能合约;如果矿工先处理交易T[2]再处理交易T[1],那么由于先执行的是T[2],合约状态就转化为S[2],最终交易T[1]执行的就是状态S[2]时的智能合约。

攻击方法举例:

攻击者提交一个有奖竞猜合约,让用户找出这个问题的解,并允诺给予丰厚的奖励。攻击者提交完合约后就持续监听网络,如果有人提交了答案的解,此时提交答案的交易还未确认,那么攻击者就马上发起一个交易降低奖金的数额使之无限接近0。当矿工处理这两个交易时,当前交易池就有两个待确认交易:一个交易是提交答案,一个交易是更改奖金数额。如果矿工先处理的是敌手更改奖金的交易,而敌手可以通过增加交易费用让矿工先处理自己的交易,那么等到矿工处理提交答案的交易时,答案提交者所获得的奖励将变得极低,敌手就能几乎免费的获得正确答案。

时间戳依赖合约,也称时间篡改;

矿工处理一个新的区块时,如果新的区块的时间戳大于上一个区块,并且时间戳之差小于900秒,那么这个新区块的时间戳就是合法的。这是以太坊协议所规定的。时间戳依赖顾名思义就是指智能合约的执行依赖当前区块的时间戳,随着时间戳的不同,合约的执行结果也有差别。

攻击方法举例:

1.一场比赛在今天午夜付出了第一名球员。

2.恶意矿工包括他或她试图赢得⽐赛并将时间戳设置为午夜。

3.在午夜之前,矿工最终挖掘该块。当前的实时时间“能够接近”到午夜(当前为该块设置的时间戳),⽹络上的其他节点决定接受该块。

以下功能只接受特定⽇期之后的呼叫。由于矿⼯可以影响他们区块的时间戳(在一定程度上),他们可以尝试挖掘⼀个包含他们交易的区块,并在未来设定⼀个区块时间戳。如果⾜够接近,它将在网络上被接受,交易将在任何其他玩家试图赢得比赛之前给予矿工以太:

 

误操作异常:

在以太坊中,一个合约调用另一个合约可以通过send指令或直接调用另一个合约的函数。然而在调用过程中可能会出现错误,调用的合约就会回退到之前的状态。那么这个异常就可能无法很好地被调用者获知,这取决于调用方式。例如,通过send指令调用的合约应该通过检查返回值来验证合约是否被正确执行。

攻击方法举例:

有个名KingOfTheEtherThrone(KoET)的智能合约:用户可以通过一定数量的以太币成为“以太币国王”,支付的数额由现任国王决定。很显然,当前国王可以通过买卖国王获得利润。当一个用户声称为国王后,合约就发送赔偿金给现任国王,并指定这个用户为新的国王。然而,这个合约并没有检查支付赔偿金的交易的结果。 这样一旦合约在执行过程中产生了异常,现任国王就有可能同时失去王座和赔偿金。

可能的攻击方式就是敌手故意超出调用栈的大小限制。以太坊虚拟机规定调用栈的深度为1024。敌手在攻击之前,首先调用自身1023次,然后发送交易给KoET合约,这样就造成了合约的调用栈超出了限制,从而出现了错误。合约出错后,因为这个合约没有检查合约的返回值,那么如果合约在发送赔偿金给现任国王的过程中出现了异常,那么现任国王极有可能失去王座和赔偿金。

链得得仅提供相关信息展示,不构成任何投资建议
本文系作者 区块链安全档案 授权链得得发表,并经链得得编辑,转载请注明出处、作者和本文链接

更多精彩内容,关注链得得微信号(ID:ChainDD),或者下载链得得App

分享到:

相关推荐

    评论(0

    Oh! no

    您是否确认要删除该条评论吗?

    分享到微信