本文主要是介绍TheDAO周年祭--攻击事件回顾及区块链固有安全性分析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
题记:若干年后,将来的新人类写《新史记》的时候,the DAO事件应该会是一个重要的篇章。
由于区块链的不可篡改的特性和存证的特长,the DAO事件的细节被完整地保存了下来,包括攻防双方的在以太坊区块链上的具体动作,如果说这是一场战争的话,那将是有史以来被最真实地记录下来的一场战争。
因为the DAO出事了,所以备受关注。但是就算the DAO没有出事,它也照样会被载入史册,因为它出现标志着一种新的人类社会的组织形式。
说了这么多,可能有人还不知道the DAO是什么?
这么说吧,the DAO其实是一个去中心化运作的基金,任何人都可以往里面打钱,打钱后有了投票权,投给你喜欢的投资项目,进而享受收益。和以前的基金会不同,不需要配备会长、经理、秘书。所有会务都是通过区块链自动处理的。不同于人性的的不确定性,开源代码的运行结果是可预期的,具有确定性。很多人期望the DAO能够投石问路,开创一种新的社会组织形态。
正所谓“code is law”,代码即法律。
人和代码,哪一个更可信?
回顾这次著名的攻击事件之前,先准备预备知识:
预备知识1:以太坊两种不同的账户
外部账户,由人类控制(通过拥有私钥)
合约账户,由代码控制(代码即法律)只有合约账户才有fallback功能
那么哪个更可信?这涉及到信任的产生,一个陌生人,你不信任他;比特币也是代码控制,但是久经考验,就产生了信任。
说明信任涉及两个要素:
时间 从事时间越长越容易取得信任
考验 涉及很多因素,比如成功应对重大危险,比如你亲身体验可行
预备知识2:fallback函数是理解的关键
以太坊的智能合约之间可以相互调用。也就是说除了人类触发以外,智能合约之间也可以通过消息调用进行触发,消息调用分为如下2种情况:
显式调用,比如A合约调用B合约的某个函数,传入什么参数,获得什么返回
隐式调用,没有函数名,没有任何参数,是如下3种情况(这个过程叫做fallback)
如果调用时,可能是函数名写错了,总之没有匹配的,就落到这个匿名函数上
当合约收到了以太币(且不带extra data时)
如果调用时没有data(像是处理一种异常情况)
学习完预备知识后,恭喜你,你就快要明白史上最复杂的黑客行为了,再加把劲,我梳理如下:
the DAO其实是一个去中心化运作的基金,任何人都可以往里面打钱,打钱后有了投票权,投给你喜欢的投资项目,进而享受收益
the DAO编写者还特别民主,考虑到一个“多数人暴力”的情况,就是你很有见解,但是大众很愚昧,你的投票被人否了,而且其他人都是多数,你因此承受了损失,怎么办?
the DAO编写者针对“多数人暴力”开发了一个功能,叫做“分裂”,就是你这个聪明人不和愚昧大众玩了,你拉上少数派另立山头!
“另立山头”就是由你这个聪明人申请建立子dao,你的钱从总dao里面打给子dao,以后你就是独立运作了。注意这里涉及了资金转移,这是关键因素
钱从总dao里面打给子dao是代码自动控制的,只要你申请了“另立山头”,且审查合理,审查通过后,经过n天的冷静期,你的钱就由代码自动打入子dao了,这是关键代码,这里因为没有考虑到fallback出错了,请看如下:
里面的withdrawRewardFor是将钱从总dao打到你的子dao合约,注意前面提到的fallback函数,发送金额到你子dao合约时会触发fallback函数
如果你特别写了fallback是再调用总dao的withdrawRewardFor呢?
代码会重新运行withdrawRewardFor再给你打钱,而扣钱的代码在第二行,永远都不会运行到!!!
所以问题:
扣钱的代码在打钱的代码后面,反面教材
两类地址设计缠在一起,这个设计比较稳妥的是打钱给外部账户(也就是打钱给人),但是因为两类地址格式和权限上没有区分,也可以打给合约,偏巧合约还有fallback功能。
fallback函数功能不合理,为啥有3种功能一起,到底是打款后处理还是处理异常的,固有设计缺陷
如果我们在以太坊的基础上设计新一代区块链系统,能从theDAO事件中学到什么呢?
启示:
资金流和信息流分开。一个没有经过检验的代码控制几亿的资金,是不稳妥的。交易链在设计上可以有这样的模式:资金流和信息流分开,对ICO特别合适。主链打款,子链记名。子链几乎没钱,谁来偷?
智能合约的定义和调用权限要分开。在主链定义,且要经过认证的才能定义。调用也分init权限和普通权限。init权限也要经过认证的才能调用,且init时可以指明参与者。
结论:
theDAO攻击事件和最近的Parity多签钱包攻击事件,分别造成了数亿美元的损失,给尚在幼年的区块链技术带来重大打击,通过对攻击细节的分析,显示作为区块链重大流派的以太坊技术上存在固有安全缺陷。失败是成功之母,这一次次的攻击提示我们要将安全性放在区块链架构设计的首要位置进行考虑,本文作了有益的探索,希望能抛砖引玉,希望区块链技术更加安全更加完善,臻于成熟。
如上就是老外画的theDAO循环攻击的一个例子,构造一个攻击合约,调用被攻击合约(其在正常的取钱函数中打钱给攻击合约),关键在于判断额度的动作在打钱之后;攻击合约精心构造了一个fallback函数,每次收钱后都调用,结果会再次调用被攻击合约(又运行到了取钱函数),打钱又触发fallback函数,也就是说打钱永远会被执行,扣额度永远不会被执行。钱就这么出去了。
这篇关于TheDAO周年祭--攻击事件回顾及区块链固有安全性分析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!