查看原文
其他

公链安全之比特币首个远程DoS漏洞详解(CVE-2010-5137)

DVP基金会 DVPNET 2023-01-26

众所周知,比特币诞生于2009年,其自诞生以来就伴随着漏洞,但是这些漏洞一直没有在区块链的历史长河中翻起很大的浪花,其中一个原因就是比特币的知名度在早些年并不高;随着近年来比特币的普及,被越来越多的人熟知,为了让更多的人了解比特币曾经出现的漏洞,不至于白走弯路,今天DVP为大家分析比特币首个远程DoS漏洞详解。

0x1 以史为鉴,漏洞即经验

比特币是区块链行业的先驱者,也就此开创了区块链的时代,比特币的出现已经推开了区块链的大门。对于众多区块链安全研究者来说,比特币曾经出现的这些漏洞是非常宝贵的学习资料,学习这些漏洞有助于我们加深对公链安全的理解,甚至可以举一反三对其他的公链进行检测


下图为引用来自比特币维基的一张表,我们能够在这里面看到比特币曾产生过的安全问题:

1. ↑ Jump up to:1.0 1.1 1.2 1.3 1.4 Attacker can create multiple views of the network, enabling double-spending with over 1 confirmation

2. ↑ Jump up to:2.0 2.1 This is a protocol "hard-fork" that old clients will reject as invalid and must therefore not be used.

3. ↑ Jump up to:3.00 3.01 3.02 3.03 3.04 3.05 3.06 3.07 3.08 3.09 3.10 3.11 3.12 3.13Attacker can disable some functionality, for example by crashing clients

4. Jump up↑ Attacker can take coins outside known network rules

5. ↑ Jump up to:5.0 5.1 Attacker can create coins outside known network rules

6. ↑ Jump up to:6.0 6.1 6.2 Attacker can access user data outside known acceptable methods

7. ↑ Jump up to:7.0 7.1 Extent of possible abuse is unknown

8. ↑ Jump up to:8.0 8.1 8.2 8.3 8.4 8.5 8.6 8.7 Attacker can double-spend with 1 confirmation

9. ↑ Jump up to:9.0 9.1 9.2 9.3 9.4 9.5 9.6 9.7 9.8 Attacking requires mining block(s)

10. Jump up↑ Local attacker could potentially determine the RPC passphrase via a timing sidechannel.

11. ↑ Jump up to:11.0 11.1 Attacking requires signing with the publicly-disclosed alert key


这份表的标注把比特币曾经出现的漏洞分为几个大类,比如说一类是标记了[1]的,代表这些漏洞可以导致比特币产生双花交易,它的产生会破坏整个生态的经济秩序,导致通货膨胀;再比如标记了[3]的这些漏洞可以导致比特币节点崩溃,节点一旦大量崩溃会使发动51%攻击更加容易。


举个例子,最近某实验室公布的信息当中,我们发现可导致NEO公链产生双花交易的MerkleTree bug最早就出现于比特币的漏洞CVE-2012-2459中。


所以今天要进行详解的便是比特币的第一个远程DoS漏洞CVE-2010-5137



0x2 图灵完备,各有优缺点

比特币和以太坊一样,都有属于自己的操作码,在比特币中由操作码组成的一段程序叫“脚本”,在以太坊中叫“智能合约”。


他们两者最大的区别就在于前者不是图灵完备的,后者是图灵完备的。什么叫图灵完备?图灵完备可以简单但不那么恰当地理解为能写循环语句、条件分支语句等的编程语言就是图灵完备的。


所以以太坊可以用智能合约打造各种各样的DApp,而比特币只能用其脚本做一些很简单的逻辑,比方说发起标准交易、冻结资金、多重签名等等。


在本案例中要讲的是在比特币0.3.5之前所使用的OP_LSHIFT操作码,这个操作码的作用是使某个数字bn1左移bn2位


0x3 漏洞成因


CVE-2010-5137

首先先下载比特币 0.3.3的源码:

https://github.com/bitcoin/bitcoin/releases/tag/v0.3.3

然后定位到/src/script.cpp595-598行

case OP_LSHIFT:
    if (bn2 < bnZero)
       return false;    bn = bn1 << bn2.getulong();
    break;

可以看到当比特币遇到OP_LSHIFT操作码时会使bn1左移bn2位,假设bn1是1的话,那么其左移1位的结果就是2^1,左移2位就是2^2。


若是一个非常大的数字的话足以引起overflow,而且在此处也没有容错处理。


本地模拟一下:

可以看到确实引起overflow了。


该漏洞在0.3.6中第一次修复,不过很尴尬,他们是这样修复的:

case OP_LSHIFT:
   if (bn2 < bnZero || bn2 > CBigNum(2048))
           return false;    bn = bn1 << bn2.getulong();
   break;

bn2不能大于2048了…这样其实还是不能阻止产生溢出的。

于是又迎来了第二次修复,这一次非常简单暴力:

if (opcode == OP_CAT ||    opcode == OP_SUBSTR ||    opcode == OP_LEFT ||    opcode == OP_RIGHT ||    opcode == OP_INVERT ||    opcode == OP_AND ||    opcode == OP_OR ||    opcode == OP_XOR ||    opcode == OP_2MUL ||    opcode == OP_2DIV ||    opcode == OP_MUL ||    opcode == OP_DIV ||    opcode == OP_MOD ||    opcode == OP_LSHIFT ||    opcode == OP_RSHIFT)
   return false;

直接把一部分Opcode给禁用了,OP_LSHIFT也在其之中。


0x4 前车之鉴

CVE-2010-5139漏洞是在2010年比特币刚诞生不久就被发现的,所以区块链软件其实并没有想象的那么安全,比特币都如此,更何况其他的公链项目呢?


然而市面上很多项目并没有以此为前车之鉴吸取教训,例如:时隔八年,BEC代币重蹈覆辙。


早在2010年时比特币就爆出过类似的数值溢出漏洞(CVE-2010-5139)导致增发了1840亿个比特币,然而在2018年时BEC代币却再度重演悲剧。


再有,前面也提到过,今年NEO由于MerkleTree bug导致的双花漏洞在比特币2012年时也曾出现过(CVE-2012-2459),完全一样的逻辑错误。


0x5 吸取教训

综述,目前造成区块链项目悲剧重演的现象主要有两个原因:第一个原因是对比特币漏洞关注度不高甚至不知道而第二个原因就是对这些漏洞的了解程度不够。


这些漏洞都是在区块链火起来之前被披露的,没引起众人的关注;其次是对这些漏洞的了解程度不够,不清楚其原理造成;对比特币漏洞的分析文章非常少,导致行业内只能看到一个CVE编号和一段简介,其它资料少之又少。


所以关于本系列的文章我们会持续更新,与大家分享比特币曾经出现的漏洞,让更多的人知道并且了解。


您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存