社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  区块链

黑客来袭!手把手带你深挖区块链安全漏洞

区块链大本营 • 8 年前 • 543 次点击  

目前,区块链漏洞安全问题频发。

 

区块链行业正面临着私钥生成与保护、共识过程中心化、智能合约代码漏洞、签名过程算法漏洞、系统实现代码漏洞等安全问题,对于以上问题,开发者该如何应对及避免漏洞频发呢?

 

吴家志(PeckShield研发副总裁、原360 C0RE Team创始成员及360超级ROOT产品负责人,专注于区块链智能合约安全以及数据分析)围绕以太坊智能合约及公链安全问题主题,先是对最近流行的Fomo3D游戏存在”薅羊毛“漏洞展开了深入浅出的分析,之后又对allowance和overflow相关漏洞做了解读,最后,又针对此前影响较大的以太坊EPoD致命报文漏洞做了深入剖析和实操演练。

那么,你对智能合约和公链安全问题了解多少?目前以太坊智能合约存在哪些漏洞?公链安全正遭受哪些威胁?如何去深入剖析区块链现已曝出的漏洞?来听一听区块链资深漏洞专家是怎么说的!

作者 | 吴家志 PeckShield研发副总裁 

责编 | kou



以下为吴家志在CSDN主办,区块链大本营、柏链道捷、极客帮创投协办的「第 9 CSDN 区块链技术沙龙」上的发言内容,区块链大本营在不改变原意的情况下作了精心整理。



我先自我介绍一下,我叫吴家志,目前在PeckShield担任研发副总。我们是今年年初转到区块链领域的,其实创业初期我们有做过一些其他的尝试,之前我的工作比较偏向操作系统安全方面,主要在安卓方向,像360 C0RE Team360超级ROOT都是我在 360期间开发出来的产品。

 


目前,区块链发展的趋势是怎样的可以看一下数据,蓝线代表创建智能合约数量的趋势。

 

可以看出,去年9月份,智能合约数量出现了大幅下滑,年底各种ICO的出现,使智能合约数量有了很大的上升,今年2月份又出现了明显的下降,过去的两到三个月也都在下降,不过7月份开始又往上涨了,这其中的原因,在场的大家都知道,我就不说了。

 

而且,至少2017年下半年开始到今年年初,由于区块链各行业DApp不断落地,行业形势看起来一片大好

 

区块链这么火,投资人会投入大量资金去买币、炒币...


但在我们安全研究人员眼里来看,它其实是黑客非常感兴趣的目标。

 


2014年的Mt.Gox的事件开始,一直到今年这个时间,出现了很多区块链安全事件。比如今年4月份有关智能合约漏洞的美链(BEC事件,5月份的EDU,到近期的交易所被黑,各类安全事件很多很多。

 

这种安全问题,它造成的结果是非常严重的,你的钱是真的不见了。不像是手机里面的照片、隐私被窃这种,这根本不是一个级别的。

 

今天我主要讲两个主题,智能合约安全公链安全



 

深入浅出:Fomo 3D漏洞

 

先讲一下智能合约相关的安全问题,近期F3D十分火爆,它有很多有趣的东西,就在6天前,我们就有一个比较新的研究……

微博:https://weibo.com/ttarticle/p/show?id=2309404265433178991610

 

这个故事是这样的,大概7 23日晚上 8点多,我在微博上发现了一条关于F3D的信息,Geth客户端开发团队的 team leader、以太坊核心成员 Peter 发现了一个F3Dairdrop()问题,这引起了我的兴趣,然后我们就去分析。



这个事情很有趣,先看右边蓝色框内,它就是F3D的智能合约之一,它其实有很多合约,今天我只讲其中一个。


其中有一个环节做airdrop(),你可以理解为它利用了彩票抽奖的机制,假设你投注F3D,不管你买了多少Key,买完之后它就有一个小概率事件,会让你中奖,然后你就会有一个额外的激励。我觉得这个设计也挺合理的,它可以活跃用户参与。

 

0.1个ETH是F3D最低的奖金,有人刻意用最低的投入去薅羊毛,他只要操作个钱,就有机会中奖。最后智能合约里面的withdraw()函数把钱取出来。

 


先看一下function airdrop()这个函数,有个名为seed的变量,seed是随机数中很重要的一个概念,计算机世界中不存在一个绝对的随机数,你只能通过seed去生成一个相对的随机数。

 

一旦你可以通过某种方法预测seed值,这个随机其实就会从小概率事件可能变成一个大概率事件

 

比如说我刚开始学编程的时候,一开始学C,我用random()函数获取随机数,我那时候还不知道seed,我就会传空值或者传零进去,然后我发现每次跑都会是同一个结果。

 

这个黑客找到了一个方式,在每次投注的时候,预测说这里一定会开奖,百分之百会开奖。确定之后他再投这个钱,所以他每次都可以从里面拿钱出来。

 

说一下这个东西是怎么被预测的?其实它的实现是这样的,可以看到seed运算里面有这么几个关键点,比如说timestampdifficultycoinbasegaslimitnumber

 

还有一个比较特别的,就是airDropTracker_,事实上这些都是合约里面的一个值,你可以随时把它读出来,所以你可以认为前面提到的全部都是已知的,唯一你不能预测的,就是msg.sender

 

当时Peter认为F3D团队假设认为msg.sender的随机性是足够的,其实 msg.sender就是你进到合约时的钱包地址,F3D团队认为你不可能生成大量的钱包去尝试,然后让seed变成可预测的,但并不是只能从钱包进来,也可以从另外一个合约进来,这个其实就是关键。



这就又涉及到一个算法,有一个叫isHuman()的函数判断,判断是真人钱包还是其他合约,但问题是这个判断有一个错误,就是Extcodesize()

 

你可以用智能合约不停地刷airdrop(),这很像一个挖矿的过程,因为智能合约生成的新合约地址是可预测的,所以你就可以一直不停的算,直到算出一个seed结果满足return(true) 时,就可以保证开奖。

 

一旦智能合约在constructor()里面去调isHuman()判断时,它就会误判,然后造成人为开奖的结果。



所以,就会出现这样一个的攻击模式——首先可以生成多个合约,然后就一直算,直到算到某一个可以搭配当下airDropTracker_的合约X时,就可以保证开奖,然后再根据合约X去投注,就可以不断把财经池里面的财经全部都拿走。

 

但其实对F3D来说,这也不是一个太大的问题。因为被攻击的财经池只是F3D整个奖金环节中的很小一块

 

所以,它就好比你玩某一个游戏,有一个外挂,你的攻击力每次都加9,保证你可以把人砍死,大概是这样,有点类似破坏游戏平衡吧,但其实对整个游戏的影响不会太大,比如说把所有人的个人资产都拿走。

 


其他智能合约相关漏洞

 

接下来讲一些其他有关智能合约安全的问题。



有一类问题是跟allowance有关的,比如ERC20里面有一个标准的APItransferFrom(),它允许某一个人把你的钱转走,但前提是事先已经声明好的,在哪里去声明?就是在allowed[]这个数组里。

 


这里有一个问题,虽然它可以允许你把钱转走,但是却无法判断你要转走多少钱,它其实是仅仅把这个allowance剪掉了,这是代码上的一个bugEDU 问题就属于这种类型。


这是我做的一个实验,我隐去了一些信息



最上面那个0xd开头的值是我的一个钱包地址,然后To指向是受我攻击的合约的地址,攻击完成后,我把0xa地址其中的一个EDU,就是好多0后面有1个的那个,转到了0x6这个地址,其实0x6也是我的钱包地址。

 

Input Data这一块是一些攻击的细节,其实这个构造起来非常简单,你只要去调transferFrom()函数,然后你就传入fromtovalue。所以,我偷了一个EDU到我的钱包,这个攻击就是这样的。

 


接下来,以batchTransfer()为例,讲一下overflow相关的漏洞,它的攻击是这样完成的。



在调用batchTransfer()函数时,有两个可以传入的参数,一个是receivers,一个是value

 

receivers是一个数组,它传入了40这个数,这个数值表示偏移量,是需要传给智能合约的。然后下面还有2或者8开头的。

 

这个逻辑是这样的,在batchTransfer()的实现上面,就是把8开头后面全部都是0的这个值,同时转给两个人

 

如果按一般的逻辑去理解,账号里必须有足够的钱才能够转过去。但问题是,在它实现检查时,它的实现方法是直接算两个数的乘积。

 

0去乘,结果是很明显的,就算用最大的字节去乘,乘完之后它也会变成0

 

所以,你可以在没有任何钱的情况下把这么多钱转给那两个人,也就是上面红色框部分,你会看到这个地方两个transfer都是这么大量的Token,美链事件就是这样,通过这种方式可以无中生有造出大量的假币,然后再把假币充到OKEx里面,然后就可以进行砸盘等各种操作。



另外一个案例和transfer还蛮像的,但稍微复杂一点,两个addressvalue都是数组。

 

它们溢出的方式一样,就是说把这些值加起来或者乘起来,然后造成的结果也是一样的,就是很大量的假币就充进你钱包地址。

 

到这里,我大概简单讲了讲智能合约方面的安全问题,其中一个是F3D薅羊毛的最新研究,还有一些过去我们发现的其他问题。

 


公链安全

 

今天的第二个主题,我讲一下关于Infrastructure方面的安全问题,就是所谓的公链安全。

 


PeckShield在以太坊公链上做了很多研究,EOS相关的也有一些

 

讲到公链问题其实你可以这样理解,比如说你用一个360手机卫士,可以理解为有一个客户端在手机上运行,然后还有各种服务端,你要发送各种请求,然后它会推送一些信息给你。

 

而在区块链里面,你可以理解为只有客户端没有服务端,至少以太坊上是这样子的,每一个节点基本上长的都是一模一样的。

 

所以,那时候我们开始进入区块链行业、研究主链安全时,我们其实就是去看所有客户端的代码,看它实现的逻辑有没有什么错误



这边是一个统计,Ethereum Nodes这个网站可以统计以太坊上都运行了哪些客户端,比如说有GethC++Parity,还有Python。所以,用的比较多的是GethParity,今天的研究主要在Geth,因为它是官方的且用户量大,对Parity也有一些研究。



首先讲Geth这一块,其实谈到任何的安全问题,我们都需要先理解这样一个事情,就比如说Geth是一个盒子,我们用什么方式可以攻破它?就是所谓的 Attack Surface(攻击面)的问题。

 

比如说可以通过一个智能合约去攻击它,那它可能就是EVM方面的问题。

 

还可以通过一个RPC接口,它就可以类比成以前那种Web安全相关的这种问题。

 

还有一种,通过协议栈攻击,这两个其实是有点不一样的。因为区块链里面的每一个客户端之间,它们会互相去同步,或者互相分享信息,所以协议栈的问题是最底层、也比较关键的问题,一旦出问题的话,整个系统可能就不运行了。所以,接下来我主要在协议栈这一方面进行一些探讨。

 


这是以太坊的协议栈,大概是这样,很多部分可能你们以前没有听到,像ETHLESWhisper是你们比较熟知的,就是以太坊的协议。然后跟它并列的还有一些其他的,它的底层其实是包含RLPxÐΞVp2p的。

 

假设说你运行过Parity或者Geth,你要同步一个full node其,实很花时间,我那时候刚开始弄花了可能有小一个月,就看你的带宽怎么样了;还有就是硬盘,我发现机械式硬盘基本没戏,一定要SSD才有可能进行同步。

 

ETH并列的协议LES,它是一个比较轻的协议,你在同步时,你不需要将所有的信息都同步,你可能只会同步一些metadata

 

所以,在运行Geth时,你可以去指定运行LES mode这种模式

 

 

接下来,详细介绍一下我们之前发现的关于LES的安全问题。

 

简单的说,就是一个越界读的问题,问题出在上面这一行代码,就在query.Skip这里。

 

我们可以自己去写一个类似于Geth的客户端,我只要知道你GethIPok。比如说有一个矿池,矿池总要有一个节点去同步到链上,我一旦知道这个IP是什么,我就可以伪造这个东西,然后让你崩溃。



那么,如何让它崩溃的?我Skip值设成-1(在协议栈上你可以自由设置),-1+1就是0,就等于说我可以尝试让你去分配一个长度为0的数组,然后我又可以去读这个数组的Skip值为-1的位置,那一定不再是你的位置了,它已经超过了你可以控制的内存范围,所以它就必然会崩溃。



接下来,演示一下这个EPoD Demo,问题出现在1810版本之前,也包括1810这个版本。




在拍摄视频时,我用的是官网上面的1810版本,对比过MD5,它是没有经过任何修改的;还需要处于离线环境,避免遭受外界攻击,保证所受攻击都来自本机;运行GethLES mode

 

然后监听从本机发出来的30303端口,在运行攻击代码后, EXP后面的地址(即本机地址)是127.0.0.1,端口是30303,此时的Geth差不多就已经崩了。

 

index out of range,崩的理由就是这样,一个越界读。它在处理某一个这种LESMessages的时候,造成了一个越界读。TCpdump就是我攻击的钱包,我们把这个漏洞叫EPoD,我只要知道你的IP,发一个包,Geth就会崩溃,大概就是这样。


还有一些攻击,我应该会在9月份举办的ISC上讲到。

 

比如说你新成立一个X交易所,然后有一个成立很久的Y交易所,你觉得它的交易量很大,想让它变小,你就可以去攻击Y交易所。

 

一旦你知道了Y交易所的IP以及它同步的node,就可以把信息扩散出去,就会忙死一片了。

 

像刚刚讲的矿池,矿池最基本的一个事情就是算力,每个矿池之间都在竞争算力,那我一旦可以让某些矿池瘫痪,这个矿池后面的算力也就没了,这也是非常严重的。

 

但是通常我知道,矿池在使用Geth的同时,也会使用Parity,两个客户端会实时进行同步。一旦我们发现 GethParity同时存在问题的时候,就十分有趣了。

 

还有就是所谓的Boot Node,这个玩过的人可能会知道,一开始同步的时候你需要知道从哪边开始同步,从哪边开始就是所谓的Boot Node

 

所以,当你瘫痪掉以太坊所有的Boot Node时,新的Geth就没有办法去同步,因为它根本没有办法启动。

 

一旦找到这种涉及公链安全而且又是协议栈的问题,就可能会遭受这些攻击的影响。

 

所以,如果Geth低于1810版本就赶紧升级吧

 

我的分享就到这里,谢谢大家!




最新热文:


扫码加入区块链大本营读者群,群满加微信 qk15732632926 入群





了解更多区块链技术及应用内容

敬请关注:


今天看啥 - 高品质阅读平台
本文地址:http://www.jintiankansha.me/t/mq3nGNqkOt
Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/22009