区块链TOP1重入漏洞之自我理解【原创】

by : 风之传说

最近在研究区块链方面的漏洞,智能合约top 1重入漏洞。在网上找了很多相关的文章,发现大部分都是通过代码进行分析。话说,我们不了解应用场景,只是了解漏洞成因,只知其原理不知其过程,不便于我们的漏洞理解。

在此之前,我们需要先了解一个东西,The DAO。"2016年6月18日被攻击前募集了$150M。攻击者 利用合约中的漏洞发动了Reentrancy攻击,获得了$60M。为了追回这部分资金,以太坊社区决定进行硬分叉,在新分支中回滚自攻击开始后的所有交易记录并修复合约漏洞,但因为此举违背了‘Code is law’精神,部分成员拒绝新分支,导致最终形成了两个分支。旧分支称为以太坊经典(Ethereum Classic/ETC),新分支为现行以太坊。攻击者最终离开以太坊经典,带走了数千万美元。"

 

以上新闻说明两个问题:

  1. 因为此漏洞,直接导致了以太坊硬分叉。(这个硬分叉什么意思呢?简单理解,就是一个树枝一分为二,你走你的,我走我的。另,你只需要了解,这个漏洞影响很大。)
  2. The DAO是一个募集资金的平台。(我们可以理解为,某某生病了,然后需要钱,然后众筹给你筹钱。这个很好理解)

技术细节

那么众筹就需要三方,付款方,公证人(平台),收款方。我们先进行简单了解。谈完了,背景,我们再来谈谈漏洞,先看一段:

 

 

大多数都没有进行注释,毕竟是新的编程语言,国内熟悉的比较少。我进行了注释。但是为了大家便于理解,我就重新解释一次。

假如账户有10个币,你要转9个出去。肯定是可以的,你要转11个,就不行。因为你没有11个。所以此处要转9个出去肯定是可以的。因为10>=9。最后一步就是减去你账户中的9个币了。此时账户里面只有1个币了。所以,各位看官肯定会说,这里没毛病啊。嗯,程序好像看似没毛病但是。看看黑客如何进行攻击的:

 

 

攻击者首先构造一个恶意合约MalloryMallory部署之后,攻击者调用withdraw函数向Mallory合约捐赠一点以太币。看似没什么问题。

withdraw函数中的msg.sender.call.value(amout)()执行之后,由于转账 操作特性 ,会在转账结束之后自动调用Mallory 的 fallback函数,于是再次调用 withdraw函数。因为此时credit中并未更新额度,所以依然可以正常取款,便陷入递 归循环,每次都提取DAO中的一部分以太币到Mallory合约中。

 

 

讲到这里,到底是哪里出了问题呢? 其实是msg.sender.call.value 这个调用出了问题。压根就不能这么调。 (所以后来出了一个什么气Gas?并且要求使用send() 和 transfer() 转币进行转账。扯远了,有空可以去了解一下)

 在这里,我们上面分析过了,我们是先进行转账再进行扣款的。那么这样有什么坏处呢?也就是说,如果在转账处一直循环卡住了,那么扣款就不会执行。也就是说,你可以一直转账下去。

 

举个流程例子:

正常情况下

 

 

不正常情况下

 

 

重复此操作,理论上能够将The DAO的以太币全部提取到Mallory。

最后肯定还有人会说,钱怎么转出来啊?别忘了,该合约是由你创建的,拿一般的众筹平台去了解,也就是说,众筹的钱最后都给你,因为是你发起的众筹。所以你还担心转不出钱来?所以,应用到实际场景,就能理解了吧。

注:由于刚接触区块链这一块,以上代码注释如果有错误欢迎指正。

posted @ 2018-08-07 17:45  风之传说  阅读(310)  评论(0编辑  收藏  举报