专栏首页区块链大本营黑客来袭!手把手带你深挖区块链安全漏洞

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

目前,区块链漏洞安全问题频发。 区块链行业正面临着私钥生成与保护、共识过程中心化、智能合约代码漏洞、签名过程算法漏洞、系统实现代码漏洞等安全问题,对于以上问题,开发者该如何应对及避免漏洞频发呢? 吴家志(PeckShield研发副总裁、原360 C0RE Team创始成员及360超级ROOT产品负责人,专注于区块链智能合约安全以及数据分析)围绕以太坊智能合约及公链安全问题主题,先是对最近流行的Fomo3D游戏存在”薅羊毛“漏洞展开了深入浅出的分析,之后又对allowance和overflow相关漏洞做了解读,最后,又针对此前影响较大的以太坊EPoD致命报文漏洞做了深入剖析和实操演练。 那么,你对智能合约和公链安全问题了解多少?目前以太坊智能合约存在哪些漏洞?公链安全正遭受哪些威胁?如何去深入剖析区块链现已曝出的漏洞?来听一听区块链资深漏洞专家是怎么说的!

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

责编 | kou

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

我先自我介绍一下,我叫吴家志,目前在PeckShield担任研发副总。我们是今年年初转到区块链领域的,其实创业初期我们有做过一些其他的尝试,之前我的工作比较偏向操作系统安全方面,主要在安卓方向,像360 C0RE Team、360超级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 发现了一个F3D的airdrop()问题,这引起了我的兴趣,然后我们就去分析。

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

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

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

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

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

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

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

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

还有一个比较特别的,就是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里面有一个标准的API叫transferFrom(),它允许某一个人把你的钱转走,但前提是事先已经声明好的,在哪里去声明?就是在allowed[]这个数组里。

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

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

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

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

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

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

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

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

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

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

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

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

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

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

公链安全

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

视频内容

在拍摄视频时,我用的是官网上面的1810版本,对比过MD5,它是没有经过任何修改的;还需要处于离线环境,避免遭受外界攻击,保证所受攻击都来自本机;运行Geth的LES 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,两个客户端会实时进行同步。一旦我们发现Geth和Parity同时存在问题的时候,就十分有趣了。

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

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

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

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

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

本文分享自微信公众号 - 区块链大本营(blockchain_camp)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2018-08-04

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 智能合约初探:概念与演变

    自2009年比特币开启区块链时代以来,近10年里,随着技术与生态的发展,基于区块链的分布式应用(dapp)呈现出井喷的趋势,而支撑着dapp的底层技术就是“区块...

    区块链大本营
  • 智能合约没你想得那么智能!5分钟带你重新认识“智能”合约

    为什么人们对区块链会产生如此强烈的兴趣?这是因为,在执行合约过程中,如果不再需要第三方信任,做事效率就会得到极大的提升。

    区块链大本营
  • 年薪百万的技术面试都问啥?来收下这份必考题葵花宝典吧|套路

    话说,区块链行业对人才的缺口越来越大,但由于区块链涉及的知识领域较为广泛,能找到真正有用的人才对每个企业来说都非常不易。

    区块链大本营
  • 如何在国内发布 UWP 应用

    在国内的开发者,相信都遇到这样的情况,辛苦开发了几个月的应用,发布到应用商店,发现只有几个下载。不断推广却发现有用户评论垃圾应用下载不了。 在国内开发 UWP ...

    林德熙
  • 如何让 HelloWorld.apk 体积最小

    按照最新 ADT 的默认设置(如下图所示)创建一个最简单的 HelloWorld 程序,会发现最后生成的 apk 文件大小就已经达到了惊人的 903KB。如果只...

    mzlogin
  • Linux 磁盘管理常用命令硬盘分区和格式化概述在VM虚拟机添加硬盘MBR分区

    JavaEdge
  • 一次代码优化实践,用了模板方法+策略+工厂方法模式

    好久没分享工作总结啦,今天来一份代码优化总结。用模板方法+策略+工厂方法模式优化了代码,耐心点看完,应该对大家有帮助的~

    捡田螺的小男孩
  • 面试官六连问拆箱装箱Integer那些事,给我整懵圈了!

    小萌:由于基本数据类型不是对象,所以java并不是纯面向对象的语言,好处是效率较高(全部包装为对象效率较低)。Java是一个面向对象的编程语言,基本类型并不具有...

    乔戈里
  • 事件、留存、漏斗分析到底是个啥?

    小五今天给大家带来的这篇文章,是关于用户精细化分析的,总体来说涉及到四个方面,分别是事件分析、留存分析、漏斗分析和分布分析。

    朱小五
  • 精细化用户增长案例:事件、留存、漏斗分析方法是什么?

    事件分析法的应用领域非常广泛,不同学者从本领域视角对其进行了阐述。事件研究是根据某一事件发生前后的资料统计,采用特定技术测量该事件影响性的一种定量分析方法。

    1480

扫码关注云+社区

领取腾讯云代金券