主页 > imtoken钱包官网app下载 > 为什么比特币的DoS漏洞如此严重?

为什么比特币的DoS漏洞如此严重?

imtoken钱包官网app下载 2023-03-22 07:06:31

比特币核心0.16.3客户端上周突然发布比特币漏洞,开发者催促大家尽快升级,让比特币界人士大吃一惊。 表面上的原因是 0.14-0.16.2 客户端中存在拒绝服务 (DoS) 向量需要修补。 直到后来我们才发现0.15-0.16.2版本核心客户端的另一个漏洞可能会导致比特币超发的问题。

在这篇文章中,作者试图解释:发生了什么? 潜在的危险是什么? 如果有人利用此漏洞,还会发生什么情况?

双花的两种方式

在开始实际利用之前,我们需要解释一些事情。 我们首先要定义双重支付,因为这个漏洞可以用来双重支付。

所谓双重支付的情况,就像爱丽丝(Alice)付给鲍勃(Bob)一枚硬币,然后她又把同一枚硬币付给查理(Charlie),爱丽丝基本上是在尝试执行两次付款,其中一次她知道会被拒绝。 当然,当我们考虑支付的时候,Alice的一些账户因为写这两笔支付而透支了。 这与比特币的运作方式非常接近,但并不完全相同。

比特币不是基于账户模型,而是基于未花费的交易输出(UTXO)。 交易的输出基本上包括地址和数量。 输出一旦被花费,就不能再被花费。 试想一个 UTXO(作为发送给你的硬币),它可以是任何数量,比如 0.413 BTC。

比特币的双重支出意味着一个硬币(UTXO)被花费了两次。 通常,这意味着 Alice 将她的 0.413 BTC 发送给 Bob,然后她将相同的 BTC 发送给 Charlie。

比特币的解决方案是将其中一笔交易包含在一个区块中,这决定了谁真正获得了报酬。 如果两笔交易以某种方式传递到多个区块,则后续区块将被软件拒绝。 如果两笔交易都在同一个区块中,该区块也会被软件拒绝。

基本上,比特币软件检测到双花,如果有双花,应该拒绝相应的块。

然而,在两个不同的交易中发送相同的 UTXO 并不是双花的唯一方法。 实际上,仍然存在同一个UTXO在同一笔交易中进行双重支付的病态情况。 在这种情况下,Alice 向 Bob 发送了两次相同的硬币。 所以,Alice 实际上支付了 0.413 BTC,但 Bob 收到了 0.826 BTC。 这显然不是一笔有效的交易,因为只发送了一个价值 0.413 BTC 的 UTXO。 这相当于 Alice 两次向 Bob 发送相同的 10 美元,而 Bob 收到 20 美元。

定义漏洞

因此,总结一下我们定义的两种类型的双花尝试:

使用两个或多个交易花费相同的 UTXO;

使用一笔交易多次花费同一个UTXO;

事实证明,Bitcoin Core 软件正确处理了第一个问题,以及我们关心的第二个问题。 任何人都可以构造这样的双花交易,但让节点接受它是另一回事。

目前有两种方法可以让交易被包含在一个区块中: A. 支付足够的费用将交易广播到网络,然后矿工将负责将交易包含在区块中;

B. 作为矿工,将交易包含在一个区块中;

(A) 除了创建交易并将其广播到网络上的节点之外,您不需要做太多工作。 (B) 要求你找到足够的工作量证明。 这也是这个漏洞的关键所在。

(A) 不是可能的攻击向量,因为这些交易会立即被标记为无效,并且网络上的节点会拒绝它们。 没有矿工的配合,这样的交易无法进入矿工的记忆,因为它们不会被传播。

(B) 是唯一出现漏洞的情况。 换句话说,要利用这个漏洞,你需要工作量证明,或者足够的挖矿设备和电力。

澄清一下,有 4 种双花交易需要处理:

1A — 多个内存池交易花费了相同的 UTXO;

1B——同一个UTXO在多个区块交易中被花费;

2A — 单个内存池交易多次花费相同的 UTXO;

2B — 单个区块交易多次花费相同的 UTXO;

这个漏洞有两个表现形式。 0.14.x版本客户端存在拒绝服务(DoS)漏洞,0.15.x-0.16.2版本客户端存在过冲漏洞。 下面我们就分别来分析一下。

拒绝服务攻击

故事始于 2009 年的比特币 0.1 客户端,该版本的代码通过拒绝案例 1B 和案例 2B(检查区块是否没有双重支出)来强制达成共识。

比特币DoS漏洞为何如此严重?

可以看到“check for conflicts”注释,负责检查每个输入是否被花费的代码。 “mark output as spent”注释下方的代码标记了 UTXO 的使用。 如果任何 UTXO 被花费超过一次,将导致错误。

2011 年,PR 443 被合并到比特币代码库中。 进行此更改是为了处理通过内存池传输的单笔交易的双重支出情况(上述情况 2A)。 此合并请求评论的目的非常明确:

“此外,区块中不包含具有重复输入的交易。 . . . 几周前有人尝试过,但这些交易并未包含在区块中。 我假设在某个地方有一个检查关闭,它会阻止这些重复的交易进入区块,尽管我没有对这个问题进行任何挖掘。 这实际上是为了防止这种明显无效的交易被中继。”

比特币DoS漏洞为何如此严重?

实际的代码更改与上面 ConnecTInputs 中“检查冲突”注释下的代码大致相同,但位置不同。 代码更改在 CheckTransaction 中运行,它处理上述所有 4 种情况(1A、1B、2A、2B)。 因此,我们在区块双花共识代码中有一些冗余,因为情况 1B 和 2B 都被检查了两次,其中一次在 CheckTransaction 中,另一个在 ConnectTInputs 中。

到 2013 年,PR 2224 被纳入比特币软件。 此更改的目的是区分共识错误(例如双花)和系统错误(例如磁盘空间不足),如 PR 评论中所示:

“它引入了 CValidationState,它存储有关块的元数据,或正在执行的交易验证数据。它用于区分验证错误(例如未能满足网络规则)和运行时错误(例如磁盘空间不足),这在过去常常令人困惑,因为用完磁盘空间会导致块被标记为无效。此外,CValidationState 承担跟踪 DoS 级别的角色(因此它不需要存储在事务或块中......)“

实际相关代码改动如下:

比特币DoS漏洞为何如此严重?

当时ConnectInputs已经被模块化成多个方法,这个函数就变成了检查双花的函数。 这里关键的变化是之前的报错改成了assert

assert 在 C++++ 中有什么作用? 它完全中止了程序。 为什么程序员会在这里停止程序? 这就是 Pull Requests 的用途。 这是当时的代码片段:

比特币DoS漏洞为何如此严重?

它将像以前一样处理案例 1B 和 2B。 函数名称从 ConnectInputs 更改为 ConnectBlock,但是 PR 443 中仍然保留了检查案例 1B 和 2B 的冗余。正如我们已经看到的,UpdateCoins 进行了第二次双花检查。 其中,CheckBlock通过调用CheckTransaction进行第一次双重支付检查:

比特币DoS漏洞为何如此严重?

由于这是第二次检查相同的内容,因此 UpdateCoins 无法通过双花检查的唯一方法是是否存在某种 UTXO 数据库或交易存储损坏。 事实上,这似乎是更改为 assert 的原因。 因为 CheckBlock 已经通过 CheckTransaction 在 UpdateCoins 之前进行了检查,所以我们已经知道一笔交易不是双花交易。 因此,PR 2224 正确地推测 UpdateCoins 中的这种状态一定是系统错误,而不是共识错误。 在这种情况下,为防止进一步的数据损坏,正确的做法是停止程序。

2017 年,PR 9049 作为比特币 0.14 的一部分被引入比特币网络。 随着隔离见证(Segwit)的加入,这是加速区块验证时间的众多变化之一,代码变化实际上非常小:

比特币DoS漏洞为何如此严重?

您可以看到添加了布尔函数 fCheckDuplicateInputs 以加速块检查。 正如我们将在下面看到的,这是一项被认为是多余的检查。 不幸的是,UpdateCoins 中的代码在 PR 2224 中被更改为系统损坏检查而不是共识检查。 在0.14.0版本的客户端中,其代码发生了更多的模块化变化,assert也发生了一些变化:

比特币DoS漏洞为何如此严重?

过去的冗余检查现在负责对块中的单个事务进行双花检查(案例 2B),并负责停止该过程。 从技术上讲,它仍在执行共识规则。 只是它在中止程序方面很糟糕。

PR 9049 是如何通过的? Greg Maxwell 给了我 IRC 上的聊天记录。

比特币DoS漏洞为何如此严重?

长话短说,当开发者讨论 PR 9049 时,他们倾向于认为区块级单笔交易双花(案例 2B)将在 PR 443 进行检查,而没有考虑 PR 2224。这使得开发者不会密切关注 PR 9049;

总而言之:

1. 2011年引入PR 443防止双花交易中继(案例2A)实际上产生了副作用,即对区块的双花共识规则检查产生了冗余检查(案例1B和2B) .

2. PR 2224于2013年推出。作为副作用,(1)中用于区块验证的代码从冗余升级到共识层;

3. PR 9049于2017年出台,针对单块单笔交易双支付(案例1B)跳过了(1)中的代码检查。 开发人员错误地认为代码是多余的,因为他们没有考虑到 (2)。 事实上,这一变化跳过了共识的关键部分。

公平地说,这些事情的汇合导致了这次破坏。

DoS 漏洞的严重性

这意味着 Core 软件的 0.14.x 版本可能会因奇怪的块而崩溃。 要使软件崩溃,攻击者需要做的就是:

1. 创建一笔花费相同UTXO两次的交易;

2. 通过充分的工作量证明,将(1)中的交易包含在一个比特币区块中;

3. 将该区块广播给0.14.x版本软件的节点;

(1)和(3)的成本并不高,而步骤(2)的成本最低为12.5 BTC。

如果您认为从博弈论的角度来看分裂网络并不是那么好,那么利用此漏洞的动机就很低。 充其量,作为攻击者,您花费 12.5 BTC 使一些完整节点崩溃。 由于无法从分裂网络中获利,攻击者无法轻易补偿自己的攻击成本。

如果这是唯一的漏洞,攻击者可能会给很多人带来不便,但这是不可持续的,因为这些受感染的节点可以简单地重新启动并连接到其他诚实节点。 一旦你拥有更长的链,恶意区块攻击就完全失去了威胁。 除非攻击者继续以每块 12.5 BTC 的成本创建块并将它们传播到具有 0.14.x 版软件的节点,否则攻击是不可持续的。

换句话说,虽然漏洞确实存在,但 DoS 攻击的经济动机相当低。

过冲漏洞

从软件版本 0.15.0 开始,核心软件引入了一项新功能,用于更快地查找和存储 UTXO,这只是引入了另一个漏洞。 当一个带有双花单笔交易的区块被包含在区块链中时,软件认为它是有效的而不会崩溃。

这意味着一个病态交易(同一个UTXO在同一个交易中被多次使用,即case 2B),0.14版本的节点会因此崩溃,但是使用0.15版本软件的节点会认为交易是有效的,这基本上是凭空创造比特币。

谈谈它是如何发生的。 0.15 中出现的 PR 10195 介绍了很多内容,但其主要目的是改变 UTXO 的存储方式,使其更有效地进行查找。 因此,它发生了很多变化,包括对早期 UpdateCoins 函数的变化:

比特币DoS漏洞为何如此严重?

请注意 assert(false) 周围的代码是如何被完全删除的。 请注意,0.15.0 中的 PR 10537 也更改了代码。

比特币DoS漏洞为何如此严重?

断言失败的条件现在取决于 inputs.SpendCoin,如下所示:

比特币DoS漏洞为何如此严重?

本质上,SpendCoin 返回“假”值的唯一方法是该代币不存在于 UTXO 集中。 但是正如你所看到的,这要求硬币是新鲜的,而不是脏的。 这些不是常用术语,但值得庆幸的是,核心开发人员 Andrew Chow 解释道:

“现在的问题是,什么时候 UTXO 被标记为 FRESH?当它们被添加到 UTXO 数据库时,它们被标记为 FRESH。但是,UTXO 数据库仍然只存在于存储中(作为缓存)。当它存储中的条目将不再是保存到磁盘时标记为 FRESH ...”

标记为FRESH的币就是进入交易存储池(内存池)的币。 攻击者可以通过 UpdateCoins 函数中的 assert 语句破坏节点。 更糟糕的是,如果硬币是脏的(基本上是从磁盘读取的),那么这可能会导致比特币供过于求。

因此,攻击者可以诱使运行 0.15.0-0.16.2 版本软件的矿工接受一个奇怪的无效区块,从而超过比特币的供应量。

过冲漏洞的严重性

这种攻击的经济动机似乎明显高于 DoS 攻击,因为攻击者可能凭空创造比特币。 但是你仍然需要有采矿设备来执行攻击,但考虑到潜在的经济激励,这可能是值得的,至少看起来是这样。

这是一个使用此漏洞的简单攻击:

1. 创建一个带有双倍支付交易的区块,它会支付给自己两次,比如50 BTC → 100 BTC;

2、将区块广播给0.15/0.16客户端的所有矿工;

以下是一些会发生的事情:

1.0.14.x版本节点会崩溃;

2. 老版本节点和其他备选客户端会拒绝这个区块;

3. 许多区块链浏览器运行在自定义软件上,而不是基于核心的,所以至少有些浏览器会拒绝该区块并且不会显示来自该区块的任何交易。

4. 根据矿工运行的软件,我们可能会出现链分裂;

有可能所有矿工都在运行比特币核心 0.15+ 软件,在这种情况下,不易受到攻击的客户端可能会停止运行。 矿工也有可能运行其他东西,在这种情况下,当他们找到一个区块时,链就会分叉。

由于这些违规行为,网络上的人们很快就找到了这个问题,可能提醒了一些开发人员,然后核心开发人员修复了它。 如果有分叉,那么到那时,将开始讨论哪条链是正确的共识链,并且可能会放弃意外超调的链。 如果确实发生了,社区可能会自愿执行回滚以惩罚攻击者。

所以对于攻击者来说,与其赚取 50 BTC,更有可能损失 12.5 BTC。 如果攻击者将支出翻倍,比如 200 BTC,那么超支漏洞持续存在的可能性就会降低,因为攻击会更加明显。

因此,从攻击者的角度来看,这不是一个好的赚钱方式。

攻击者获利的另一种方式是在执行攻击之前预先做空比特币。 这也是有风险的,因为攻击并不能保证比特币的价格会下跌,尤其是在迅速果断地处理危机的情况下。 此外比特币漏洞,考虑到大多数交易所都提供杠杆交易,因此需要 AML/KYC,这可能会导致攻击者很快暴露。

攻击者不仅面临巨大的财务风险,而且还面临身体上的风险。 从经济的角度来看,这不是一个容易从中获利的漏洞。

当然,一些别有用心的人可能会利用这个漏洞来恐吓那些比特币持有者。 投资回报会变得更加抽象,所以理论上,这可能会达到这些别有用心的目的。

综上所述

毫无疑问,这是一个相当严重的漏洞。 尽管我与 Awemany 存在分歧,但我很感激他选择公开辩论我。 也就是说,根据经济博弈论,我认为漏洞不会像他描述的那样严重。

即使漏洞在被发现之前被坏人利用,攻击者也可能不会选择利用它,因为从经济上讲这没有意义。 诚然,这个技术漏洞应该被修复,开发者应该做的更好,但真正能利用这个漏洞的人很少,基本上只有那些想要摧毁比特币的组织。 会这样做。

比特币核心开发人员的经验教训很多:

1. 任何共识变更(即使是很小的变更,比如9049),都需要更多的人来审核; 2、病态交易需要更多的检查; 3. 代码库中哪些检查是冗余的,哪些检查不是冗余的,实际代码要做什么,需要变得更加清晰; 4.漏洞过去存在,将来也会存在。 现在学习和反思这一课很重要;