目录
一、总述
二、第一个维度:双花攻击
1、51%算力攻击
(1)贿赂攻击
(2)币龄累计攻击
(3)通用挖矿攻击
2、芬尼攻击
3、种族攻击
4、分割攻击
5、重放攻击
(1)一条链上的重放攻击
(2)分叉链上的重放攻击
二、第二个维度:可用性的攻击
1、粉尘攻击
2、空块攻击
3、女巫攻击
4、无利害关系
三、第三个维度:规则及智能合约层面的攻击
1、整数溢出攻击
2、可重入攻击
3、交易顺序依赖攻击
4、时间戳依赖攻击
5、调用深度攻击
当我们强调区块链上的数据难以篡改、去中心化特性时,区块链的攻击也是无时不在的。在区块链的Token经济下,智能合约漏洞、黑客攻击等攻击方式层出不穷。这些攻击来自很多地方,不仅仅是区块链本身的不完善,还包括一些钓鱼网站、对交易所的DDoS攻击、欺骗等手段。
目前对区块链的攻击分为三个维度:
(1)双花问题,就是一笔钱花了两次。传统的互联网是无法避免双花的。通常来说,如果利用区块链技术,双花问题可以解决,因为区块链只承认第一笔交易为有效交易。但也可以找出方法攻击区块链从而实现双花。例如我们熟悉的51%攻击、重放攻击等。这种攻击的破坏性非常大。
(2)对区块链系统的可用性攻击。类似于传统的DDoS攻击,让区块链停止处理网络中有价值的交易和数据,从而让整个系统停止。这包括抬高处理交易成本堵塞区块链的粉尘攻击,拒绝打包交易的空块攻击,破坏对等网络的信誉系统的女巫攻击,以及在一些特定共识算法下的强行分叉攻击“无利害关系”。
(3)对区块链规则的攻击,对智能合约的攻击。是目前最要命的攻击方式,特别是针对目前的ERC20协议下的各种token来说,已经有好几个token因为合约漏洞“被增发”,直接导致了token价值归零。代码总是会有错误和没有考虑周到的地方,有缝隙的地方黑客就可以利用,比如”theDAO”事件里的无限调用攻击。
双花攻击就是同一笔钱被花费了两次。比如在最近的一次交易里,攻击者转账到你的账户100个BTC,换取了你500w人民币。钱到手后,攻击者又发送了一个转给自己100BTC的交易,不管他用了什么方法,最后最长的链上包含了这个攻击者转给自己的交易,而他和你之间的交易却因存在于较短的分叉中而被认为是“没有发生过”的。
双花攻击有多种实现的方法,成本其实不高,大家比较熟悉的就是51%算力攻击,这种攻击是通过控制网络51%的算力实现双花。如果攻击者控制了网络中51%以上的算力,那么在他控制算力的这段时间,他有非常大的可能追上当前区块产生的速度,从而将区块逆转,进行反向交易,实现双花。实现逻辑如图所示:
在中本聪的白皮书中说道,理论上无法通过技术来防范51%攻击,于是通过经济学原理来避免,使达到全网51%的算力成本非常高。虽然一再强调51%的攻击成本之高,让其从经济上来说很难发生,比特币的51%攻击是不可能发生的,但对于小规模的山寨币来说,攻击成本并没有想象的那么高。以下是几种低成本进行51%攻击的方法:
不用为了进行双花攻击去花大成本掌握51%的算力,只要拿出足够丰厚的奖励收买挖矿节点做特地的事情就好了。贿赂攻击的基本流程如下:
攻击者将贿赂声明通过地址加密私发给每一个矿工,并告诉矿工,我只告诉你一个人,这样你挖出来的区块奖励是你一个人的。如此一来,你就不会告诉别人来分走自己的奖励。这就出现了囚徒困境的博弈难题,矿工为了自己的利益不会告诉其他节点自己接受了贿赂,并且相信只有自己对区块链攻击,起不到什么关键作用,不会造成严重问题。但攻击者会把这条消息发送给起码51%以上的矿工,所以最后双花总是会完成的。
防范:引入有保证金和惩罚措施的改进版挖矿机制。每个区块链的矿工都有保证金押在链上,如果贿赂者进来告诉你去做出对原来区块链不利的决策,你会损失你所有的保证金,这样做是得不偿失的。未来以太坊的共识算法就会采取抵押保障金的方式进一步增加作恶成本。
这种攻击主要针对“POW+POS”混合共识机制的区块链。这种共识之下,挖到区块的可能性不仅与当前的算力有关,同时也与你账户上持有的币的数量和币龄相关。你拥有的币越多,持币时间越长,对于你来说挖矿的算力难度就越低,就越有可能挖到区块。这就导致,部分节点买入一定数量币后,持有足够长时间后,就有能力利用币龄的增加,近乎的达到51%的算力,从而控制整个网络。
防范:对持币数量和持币时间的最大值进行约束和预警,打到51%临界情况时,系统可以自动进行一次奖励清算,清空持币时间。
这种攻击主要针对还未形成挖矿规模的币种进行攻击。比如早期挖BTC的矿机也可以挖BCH,而且BTC的全网算力比BCH的大了好几十倍,这时候如果挖掘BTC的大矿场突然转而去挖掘某种山寨分叉币,马上就可以拥有山寨币全网的51%以上的算力,这时候对山寨币进行双花攻击,变现后继续回去挖掘BTC就好了,山寨币归零也和攻击者没有关系了。
攻击案例:2016年8月份,基于以太坊的数字货币Krypton遭受来自一个名为“51%Crew”的组织通过租用Nicehash的算力,进行51%攻击,导致该区块链损失约21,465KR的代币。
防范:修改代码,更新共识算法,使得其他区块链上的矿机无法在本区块链上进行通用挖矿攻击。
芬尼攻击中,攻击对象主要针对的是接受0确认的商家。该攻击主要通过控制区块的广播时间来实现双花,需要等待攻击者挖到一个包含自己转给自己的区块后,扣住区块不广播从而进行攻击,所以也叫扣块攻击。如图为芬尼攻击示意图(感觉有问题,修改了一下):
0确认是指一笔交易被广播到全网,即将被打包进入区块前的状态。因为区块链目前的出块时间过慢,交易确认需要等待的时间较长,部分商家为了节省时间接受0确认的交易,也就是你把交易信息填写好之后广播到全网就可以了,不需要等待打包入区块。
防范:非常简单,不接受0确认就好。
该攻击主要是控制矿工费来实现双花,同样针对接收0确认的商家。挖矿的矿工都是逐利的,他们会首选筛选手续费高的交易进行打包处理,种族攻击正是利用这一点进行攻击。
防范:商家不接受0确认,至少需要等待一个确认。
因为区块链是基于互联网的信息传递的,劫持BGP(边界网关协议)可以实现对区块链节点流量的误导和拦截。节点的流量一但被接管,又能对整个区块链网络造成巨大的影响,破坏共识机制、交易等各种信息。
从2016年11月5日至2017年,通过对节点网络的分析统计发现,目前大多数比特币的节点都托管在少数特定的几个互联网服务提供商上,而60%的比特币连接都是在这几个服务商。所以这几个服务商的角度可以看到60%的比特币流量,完全可以接管这部分流量,对区块链造成巨大的破坏。其他的币种这个情况更加严重。
攻击者可以利用BGP劫持,将区块链网络包括网络中的节点划分成两个或多个无法通信的独立网络,此时的区块链会分叉为两条或多条并行链。这时候可以在并行的分差上消费代币的转账行为,在攻击停止后,区块链会以最长的链为主链重新统一起来,其他的分叉将被废弃,这些链上的交易将全部无效。从而就实现了双花,甚至是多次花费。
防范:针对的区块链建立其专用的网络,不再让互联网服务提供商代理网络,这个专用的区块链网络同样需要去中心化,减少被单点劫持后造成巨大破坏的可能。同时设立算力监控网站,实时汇报全网算力变化情况,算法发生激烈变化就可以检查和其他节点之间的通信。
重放攻击指攻击者再次全网广播一个在区块链网络上窃听截取到的交易消息,进行欺诈实现多次收账。放攻击能导致多次付款,却不需要来自付款者的同意。
使用UTXO结构的区块链是天然抵抗重放攻击的,因为转账是基于每一笔UTXO(未花费交易输出)进行的原子级别操作,不存在一笔UTXO被重复扣除的情况,这是不合法的。
在以太坊等账户体系下的区块链中,重放攻击一笔交易会导致转出账户中的余额反复减少,收款账户中的余额反复增多。
攻击者首先进行一笔收款的交易,比如从交易所提现,然后在网络中抓取此条交易的数据,对时间戳等进行修改(此时交易的hash值已经发生巨大变化,网络会认为是一个新交易),然后在全网中再次进行广播。矿工收到这个交易后,因为交易中私钥签名和公钥加密齐全,判定为受害者发送来的交易,检查余额也足够,视为合法交易,进行打包。这样攻击者就又从受害者处收到了一笔转账,这样多次进行,直到扣完受害者商户余额为止。
防范:在以太坊的账户机构中存在一个参数nonce,他的值等于从这个账户中发出的交易的数量,交易其它验证通过和执行完成后,发送者账户中的nonce会自动增加1。当一笔交易被矿工验证是否合法的时候,矿工会比对交易包含的nonce值,并与该交易发送者账户中的nonce值进行比较,相等才算作合法交易,对它进行打包出块。重放攻击是无法修改发送者账户的数值的,只有发送者有这个权利。
交易延展性攻击:在现实生活中,纸币在使用中,可能由缺角或污迹,但这张纸币的购买力没变,只是外观看上有些不同,我们还可以用它进行交易,这就是纸币的“交易延展性”。在比特币中,因为矿工验证交易签名使用的openssl兼容多种编码格式,所以在交易发出后、确认前,对交易的签名进行编码格式的调整,虽然签名没有变化,但是交易Hash得到的交易ID却发生了巨大的变化,会被矿工误认为是一个新交易。黑客利用比特币的这个“交易延展性”,在交易所提现,在到账前,通过篡改签名编码格式获得交易ID不同的交易,进而欺骗交易所称未收到转账,实现多次提现。
攻击案例:2014年2月25日,日本时间上午11点,MT.GOX交易所(俗语门头沟)因收到重放攻击损失85万枚比特币,当时币价值近4.54亿美元,这直接导致了MT.GOX的倒闭。MT.GOX是当时比特币最大的交易所,一度交易量达到所有比特币交易的80%。这次攻击直接导致了比特币价格暴跌到原来1/3的位置。
该攻击是在存在分叉币的情况才会出现。在进行分叉产生新币种之后,代码修改的较少,导致在其中一条链上的交易在另一条链上很可能是完全合法的。所以你在其中一条链上发起的交易,攻击者可以复制到另一条链上去重新广播,也会得到确认。这就是区块链特色的“重放攻击”。
普通用户在主链分叉为两条链的时候,同时拥有了两条链的资产,分叉链上的重放攻击可能导致一条链上的资产被盗取。在交易所中的分叉币之间,不断存取一种币,可能会导致另一种分叉币无故流失,如图为对交易所进行的重放攻击(感觉有问题,对其进行了修改):
防范:最简单的办法就是在刚开始分叉时就对代码进行足够多的修改,起码要做到分叉链和主要链之间的交易信息不通用,这就可以避免损失。还有就是在分叉之后立马对不同链上的财产进行转移,不要再存在分叉前的地址里。
对可用性的攻击就是让区块链停止处理网络中的有价值的交易和数据,从而让整个系统停摆。方法很简单,比如发送大量垃圾交易堵塞网络,或者恶意分叉让节点无法寻找最长链。
实现粉尘攻击有多重手段,有的是作为交易的发起者,在全网发送很多手续费高但是转账金额非常小的交易,矿工就会优先打包这些交易,从而堵塞区块链,如此成本较高;或者直接由矿池进行攻击,挑选自己发出的无意义交易进行打包,如此攻击成本基本为0。
攻击案例:在过去两年中,比特币一直在被迫处理很多垃圾交易,背后有6到7个矿池向网络发送了大量垃圾交易,导致比特币网络拥堵。在2016年之前比特币的垃圾交易很少被矿工打包,直到2016年下半年,有7大矿池突然开始接受这些垃圾交易,这7家矿池分别是:1-Hash、Antpool、BitClubNetwork、BTC.com、HaoBTC、KanoCKPool以及ViaBTC。
一个有趣的例子:教你玩坏朋友的EOS账户。向你的朋友发送很多笔0.00001EOS的转账,你并且每次都把转账备注里的128个字符写满,这样这些交易就会发送到你的朋友的账户上,占满他的账户的4KB的内存,从而无法进行任何操作,他的EOS账户必须购买RAM才能继续进行操作,这样就玩坏了你朋友的账户。
防范:很需要矿工们达成共识,决绝打包交易量过低的垃圾交易,为了区块链的价值更多的打包有价值的交易,这样币才会进一步升值,属于用经济原理解决问题。
挖矿的矿工拒绝打包网络中的交易,在成功挖出的区块中,除了挖矿奖励的coinbase交易外,没有其他交易,这就产生了一个”空块”。 个别情况下偶尔出现一次空块,是没有问题,但短期内频繁空块就属于空块攻击了,其效果是使待确认交易内存池变大,交易平均确认时间变长。
当然可能会存在进行恶意攻击的矿工,这种情况下类似一51%算力攻击,而且空块攻击相比是没有任何受益的,矿工没有理由这么做,这是利用了经济学原理。
攻击者通过创建大量的假名标识来破坏对等网络的信任基础,并对一致的共识的达成造成巨大影响,破坏了系统的冗余策略,比如操纵区块链选举,“刷赞”“灌水”等。
在区块链这种对等网络中,因为节点可以随时加入退出,为了维持网络稳定,同一份数据通常需要备份到多个分布式节点上,这就是数据冗余机制。如果网络中存在一个攻击者,这个攻击者可以创建多重身份,攻击者可以掌握很多个“马甲”节点,原来需要备份到多个节点的数据,被攻击者欺骗,全部备份到了由攻击者创建的节点上。
在对等网络中,节点是一个抽象的概念,并且因为隐私问题,节点和拥有节点的人是割裂的,所以一个远程的节点可以识别另一个节点,却不必知道这个节点与物理世界的人的对应关系。
防范:在POW共识算法下,女巫攻击是无效的。。女巫攻击主要是针对使用BFT拜占庭容错协议的区块链,在这种情况下有两种解决方法:(1)基于第三方的身份认证:每加入一个新的节点都需要与某一个可靠的第三方节点进行身份验证;(2)纯分布式的身份认证:每加入一个新的节点都需要获得当前网络中所有可靠节点的认证,这种方法采用了随机密钥分发验证的公钥体制的认证方式,需要获得网络中大多数节点的认证才能加入该网络。
出块者可以无成本地选择接受多个分叉,以获取更多的收益,导致市场不知道哪个链是真正的账本。这是只有POS机制才会出现的问题,在POS共识机制下,节点持有的token数量决定了挖出区块的可能性。
由于他们没有花费物质上的算力,只用token进行投票,“挖矿”是0成本的。不管哪条分叉成为最长链,矿工都会得到奖励,没有必要回归最长链,这变向鼓励了分叉的出现,这种情况下,任何的交易都可能出现上文讲的分割攻击的情况,当前区块链已经不再可信。
防范:在ETH上,提出了Casper的POS/POW混合共识机制,这是一种基于保证金的经济激励共识协议,可以惩罚所有的恶意行为,恶意分叉的代价是非常大,避免了“无利害关系”攻击。矿工想要挖矿必须抵押一定数量的ETH所谓保障金。
区块链存在一种“代码就是法律”的精神,智能合约具有强约束力,但创造一个完全无误差的代码是不可能的。代码书写的合约具有法律效力,并且在一个不可改变的公开的区块链中存储信息,这造就了巨大的风险和问题,这是区块链安全问题的重灾区。
在程序语言中,对整数类型的变量一般都会有最大值和最小值。合约中的整数也会有相应的最大值和最小值。一旦变量所存储的值超过了最大值就会发生整数上溢错误,导致变量最后存储的值为0,反之则是整数下溢错误,变量最后存储的值为变量最大值。
在智能合约中的余额,通常由无符号整数表示,在ETH的编程Solidity中,通常有256比特数字。当无符号整数下溢或上溢时,它们的值立马就改变了。例如减去一个比余额还要大1的数就会导致下溢,结果余额会得到一个很大的数65535,凭空就创造出了很多的token。
攻击案例:基于以太坊的多个ERC20智能合约就遭受过整数溢出漏洞的影响。如2010年8月15日,比特币区块链中凭空出现了大量比特币,就是因为比特币的验证机制存在大整数溢出漏洞,大整数溢出为负数。
防范:书写代码时总是检查代码中的下溢或上溢,最好的方法是看更新的状态是否在字节范围内。使用安全库协助检查,例如SafeMath或者OpenZeepelin。
如果一个智能合约的功能模块在完成运行前,被调用了很多次的话,这就给了可重入攻击的可能。
攻击案例:不得不提及区块链历史上最臭名昭著的“TheDao”事件。TheDAO的智能合约中有一个splitDAO函数,splitDAO函数被第一次合法调用后会非法的再次调用自己,然后不断重复这个自己非法调用自己的过程。
防范:需要让合约的余额状态在资金发送之前更新,而不是之后,这样就不会存在多次重复调用,不断转账的情况。同时对智能合约的Gas进行验证,如果出现无限调用的情况,会拒绝执行。
智能合约的执行会随着当前交易处理顺序的不同而产生不同的结果。
比如,攻击者发布一个解题合约,在合约中写给出丰厚的解题奖励。等有人提交了正确答案后,答案再经过其他节点的确认,合约才会执行奖励操作。此时攻击者可以提交一个将奖励额度调低的交易,这笔交易肯定是在奖励操作的后面,理论上不会造成给答题人带来损失。
但是,在区块链项目中,交易顺序并不是一成不变的,例如在以太坊中,交易顺序就会随着交易发布者的gas(交易费)的高低来决定先确认哪笔交易。此时若攻击者更改奖励额度的交易给的交易费比较高,验证节点会先执行这笔交易,最终会导致答题人最后得到的奖励额度是调低的额度。而攻击者以一个较低的成本就买到了正确答案。
时间戳依赖顾名思义就是指智能合约的执行依赖当前区块的时间戳,随着时间戳的不同,合约的执行结果也有差别。
攻击案例:如果有一个抽奖合约,要求由当前的时间戳和其它可提前获知的变量计算出一个“幸运数”,与“幸运数”相同的编码的参与者将获得奖品。那么矿工在挖矿过程中可以提前尝试不同的时间戳来计算好这个“幸运数”,从而将奖品送给自己想给的获奖者。
在合约虚拟机中,会对智能合约的互相调用的深度定一个阈值,超过这个深度调用就会失败。例如在以太坊EVM中,调用深度被限制为1024。如果攻击者发起一系列的递归调用,让栈深度到达了1023,之后它再调用你的关键函数,就会自动导致这个函数所有的子调用失败。
调用深度攻击可以让合约调用失败,即使这个调用在逻辑上不存在任何问题,但是在虚拟机层面以及不被允许了,因为调用深度达到了虚拟机中的阈值,超过阈值不再往下执行。攻击者可以通过控制调用深度,来使某些关键操作无法执行,例如:转账、余额清零等。
攻击案例:比如在区块链上实现一个拍卖的智能合约,由于拍卖过程中可能存在多次竞价,需要很多次的调用合约中的出家函数,可能会出现有用户恶意刷出价次数,直到虚拟机中的调用深度达到1023次的临界值,然后再成交,发送转账请求,此时调用转账的sent()函数就会失败,导致财产损失。
参考文章:http://bitjia.com/mingci/1593.html