本文共 1848 字,大约阅读时间需要 6 分钟。
比特币自诞生以来,伴随着一系列安全漏洞的出现。这些漏洞虽然在早期阶段对比特币的生态影响不大,但随着比特币的普及,了解这些漏洞对理解区块链安全至关重要。本文将详细分析比特币第一个远程DoS漏洞CVE-2010-5137。
比特币作为区块链行业的先驱,其漏洞成因值得深入研究。这些漏洞不仅为安全研究者提供宝贵的学习资料,也为后续的区块链项目敲响了警钟。通过分析比特币历史上的漏洞,可以更好地理解公链安全的核心挑战。
下图引用自比特币维基的一张表格,列举了比特币曾经出现的安全问题。这些漏洞可以分为几大类:导致双花交易的漏洞、协议硬分叉漏洞、节点崩溃漏洞等。例如,标记[1]的漏洞可能导致双花交易,破坏经济秩序;标记[3]的漏洞可能导致节点崩溃,使51%攻击变得更加容易。
值得注意的是,最近某实验室发现的NEO公链双花交易漏洞,其根源与比特币的CVE-2012-2459漏洞有关。这表明同一类逻辑错误可能在不同项目中多次出现。
比特币和以太坊在操作码系统上有明显差异。比特币的脚本语言不具备图灵完备性,而以太坊的智能合约语言则是图灵完备的。这种差异直接影响了两者功能的扩展范围。
以太坊的图灵完备性使其能够支持复杂的智能合约应用(DApp),如去中心化交易所、金融智能合约等。而比特币的脚本语言只能支持简单的逻辑,如标准交易、多重签名等。
在本文中,我们将重点分析比特币0.3.5之前使用的OP_LSHIFT操作码。这个操作码用于将某个数字bn1左移bn2位。
CVE-2010-5137是比特币第一个远程DoS漏洞。它源于OP_LSHIFT操作码在处理数字时的溢出问题。
通过下载比特币0.3.3的源码(https://github.com/bitcoin/bitcoin/releases/tag/v0.3.3),我们可以在src/script.cpp的特定行找到相关代码。OP_LSHIFT操作码的实现如下:
case OP_LSHIFT: if (bn2 < bnZero) return false; bn = bn1 << bn2.getulong(); break;
这个代码段没有进行溢出检查,因此当bn1左移过多时,会导致整数溢出。例如,bn1=1,bn2=1,结果会变成2^1=2。然而,当bn2非常大时,bn1 << bn2.getulong()会导致溢出。
在0.3.6版本中,开发者尝试修复这个漏洞,添加了bn2的范围限制:
case OP_LSHIFT: if (bn2 < bnZero || bn2 > CBigNum(2048)) return false; bn = bn1 << bn2.getulong(); break;
然而,这个修复并不完全有效,因为bn2仍然可以达到2048,导致溢出问题仍然存在。最终在0.3.6之后的版本中,他们采取了更激进的措施:禁止了一系列可能导致溢出的操作码。包括OP_LSHIFT在内的多个操作码被直接禁用。
CVE-2010-5139漏洞是在比特币诞生不久后被发现的,导致了超过1840亿个比特币的增发。这一事件提醒我们区块链软件的安全性并非一帆风顺。
然而,许多项目在面对类似问题时并未吸取教训。例如,在2018年,BEC代币重演了类似的悲剧,导致用户资金的大量丢失。这些事件表明,区块链项目在开发和安全性上需要更加谨慎。
此外,NEO因MerkleTree bug导致的双花交易漏洞,实际上与比特币的CVE-2012-2459漏洞具有相同的技术根源。这再次证明,类似的逻辑错误可能在不同项目中多次出现。
综上所述,区块链项目的悲剧重演主要有两个原因:一是对比特币漏洞关注度不高甚至不知道;二是对这些漏洞的理解程度不够。
这些漏洞大多在区块链火爆之前被披露,但未引起广泛关注。对这些漏洞的了解程度不够,导致行业内资源有限,大多只能看到CVE编号和简介,缺乏深入分析。
为了更好地保护区块链生态,我们需要持续关注和学习这些漏洞的原理和影响。通过分析比特币的漏洞,我们可以为其他项目提供宝贵的经验,避免重蹈覆辙。
未来,我们将持续更新关于比特币漏洞的文章,分享更多信息,以帮助更多人了解这些关键问题。
转载地址:http://twwj.baihongyu.com/