比特币任意盗币漏洞浅析

当前位置:首页 > 币圈百科 > 比特币任意盗币漏洞浅析

比特币任意盗币漏洞浅析

2023-01-09币圈百科258

本期的漏洞话题是比特币漏洞CVE-2010-5141,它可以导致攻击者盗取任何人的比特币,危害非常严重。好在这个漏洞没有被利用,修复速度极快。该漏洞与比特币的脚本引擎有关,对公链开发者有参考意义;从目前市场上的公链来看,大部分都蓑衣网小编2022内置了虚拟机或者脚本引擎来打造DApp生态,这也是区块链的大趋势之一。

一、比特币中的UTXO模型是什么?

温馨提示:漏洞的代码片段中会涉及到UTXO的一些相关知识和概念,所以在对漏洞进行理论分析之前,你需要了解这些知识点。已经知道的可以直接跳过。

。Account model和UTXO model

在我们看UTXO model之前,先说一下常见的account model。什么是客户模型?模型简单的数据结构可以理解为“账号=余额”,每个账号对应一个余额。例如,账户A向账户B转账200,在账户模型中只需要先A-200再B-200就可以完成转账操作;目前大部分软件都采用账户模型,如银行系统、以太坊等。

比特币则采用自己开发的UTXO模型。UTXO中没有“账号=余额”这种数据结构,那么怎么转账呢?

二。比特币如何操作转账[X] [X]以上面A到B的转账为例。在UTXO中完成此传输需要以下操作:

1。找到账户A下余额200的来源,也就是找到这笔交易x

2。其中A收到200。以交易X为输入,以转账200给B的交易Y为输出,X对应Y,X和Y的转账金额一定相等

3。x交易被标记为失效,Y交易被标记为未失效

两笔交易的转账金额必须相等。简单的解释就是,你只能转出你收到的那么多,实际上就是这样。

但是当我不得不只转让一部分给别人的时候怎么办?答案是只转一部分给别人,剩下的再用另一个号码转给自己。

。引用两张来自网络的图文:

账户模型图片1

蓑衣网小编2022

UTXO模型

在本文中,比特币为什么采用UTXO模型不是重点,我们只能了解UTXO的原理。图片2

二。比特币脚本引擎

比特币脚本是非图灵完整的。比特币使用自己定义的脚本进行交易等操作,为比特币提供了有限的灵活性。实现简单的功能,如多重签名,冻结资金等。但再多也不行。

比特币之所以这么做,是为了牺牲一定的完整性来保证安全性。比特币脚本的原理是先定义一堆操作码,然后脚本引擎基于栈逐个执行每个操作码。

栈很好理解。队列是FIFO,而栈正好相反。这是先进先出。将一个元素推入堆栈后,它将是第一个弹出的元素。

在比特币早期版本中发送标准转账(pay-to-pubKey)交易需要脚本签名(scriptSig)和公钥验证脚本(scriptPubKey)。具体处理流程如下:

首先填写要执行的脚本,然后签名(sig)然后操作码OP_CHECKSIG会验证签名等。如果验证通过,就把true压入堆栈,否则就把false压入堆栈。

三。CVE-2010-5141的漏洞分析图片3

了解以上知识后就可以开始分析CVE-2010-5141漏洞了。作者下载了有漏洞的版本0.3.3。下载地址在github的比特币仓库里。找到释放。

script.cpp代码片段VerifySignature函数:

每笔交易都会调用VerifySignature函数,用来执行脚本和验证签名,然后标记交易是否已经花掉。

首先,txFrom参数是最后一个事务,txTo是正在处理的事务。如果你理解了上一章解释的UTXO模型,这里就不难理解了。 看1125行代码,调用EvalScript函数,第一个参数是txin.scriptSig(包含签名信息)分隔操作码OP_CODESEPARATOR?Txout.scriptPunKey(包含公钥信息和OP_CHECKSIG指令),这些是EvalScript函数要执行的脚本,下面的参数可以暂时忽略。只要EvalScript函数返回true,这个验证签名就会通过。EvalScript函数如何返回true?4

首先栈不能为空,然后栈顶强制bool后必须为真。作者简单解读为必须有栈顶,值不能为0。

然后再看关键的OP_CHECKSIG操作码1

(注:由于操作码太多,本文针对OP_CHECKSIG操作码)

以上代码不难理解。调用Checksig函数来验证签名,然后将其返回给FSuccess变量。如果是真的,请按一。如果操作码是OP_CHECKSIGVERIFY而不是OP_CHECKSIG,让vchTrue弹出堆栈,开始执行下面的操作码。

按照OP_CHECKSIG的正常逻辑,如果签名验证不成功,会在栈顶留下一个vchFalse。虽然栈不为空,栈顶的值为0,但还是会返回false。

2回到前面的代码,EvalScript函数执行的脚本主要由以下变量组成:

1。txin.scriptSig

2。OP_CODESEPARATOR

3。Out.scriptpubkey

第一个签名信息是可控的,第二个只是一个分隔符,会被删除,第三个是不可控的,因为来自最后一个事务。

第一个变量是可控的,它是作为脚本执行的,所以这个变量不仅可以是签名信息,也可以是操作码,很好处理。需要在下面引用一个神奇的操作码吗?OP_PUSHDATA4,我们来看看比特币0.3.3如何处理这个操作码:

先获取操作码。如果操作码的值小于等于OP_PUSHDATA4的值,则将vchPushValue压入堆栈,然后跟进GetOp函数

。翻看源代码,发现OP_PUSHDATA4指令定义为78,所以当函数遇到OP_PUSHDATA4时,指针会进一步移动78 ^ 4=82位,其中78位数据会被推入堆栈。所以只要在txin.scriptSig中注入一个OP_PUSHDATA4操作码,下面的公钥信息和OP_CHECKSIG指令就会被“吃掉”,作为参数放入堆栈。当指针走到终点时,做出最终判断:

1。栈是空的吗?而不是图片4

2。顶部元素是0吗?不是

图片5蓑衣网小编2022,所以满足条件时EvalScript函数返回true,然后VerifySignature函数也返回true。由于绕过了签名验证,别人的比特币就可以随意花了。

四。CVE-2010-5141漏洞修复方案

笔者下载了比特币0.3.8版本,直接看了关键部分代码

修复方案也很清晰。无论您编写什么脚本,scriptSig和scriptPubkey都是单独执行的。

写在最后:

因为比特币漏洞分析是从DVP第一期漏洞专题开始连载的,目前的素材是2010年的。目前漏洞分析主要有以下难点:

1。关于漏洞的信息非常少。大多数漏洞只有一个CVE号和简介,不查阅大量资料无从下手。3

2。环境很难搭建,比如编译,私链搭建(早期比特币甚至没有私链的概念)等。比特币早期源代码编译所需要的很多依赖项,现在已经不维护,离线了。

基于这些原因,笔者只做了理论研究,没有进行实践验证。如有错误,请指正。

五、参考链接

https://bitcoin . stack exchange . com/questions/37403/which-release-fixed-CVE-2010-5141-攻击者-可以消费-任何-硬币

比特币任意盗币漏洞浅析 | 分享给朋友: