MerkleTree底层实现问题及CVE20122459分析
前言
区块链项目态势汹涌,在经历了比特币、以太坊时代之后,大量拥有着不同特点与优势的公链项目如雨后春笋般层出不穷,吸引着人们的眼球。
这些项目既拥有区块链1.0、2.0时代中,数字货币交易、去中心化、支持智能合约的特征,也通过更加巧妙的共识机制、更复杂的技术和金融模型,来解决现有的种种问题,助区块链技术步入我们的生活。
在此期间,长亭科技区块链安全组也在关注着诸多公链项目,为这些公链项目的发展与上线保驾护航。在此前一项公链审计的项目过程中,我们发现了一个有意思的关于 Merkle Tree 底层实现漏洞。下面将分享发现该漏洞的前期技术积累,以及发现过程。
公链项目审计
回顾2018年,对于区块链安全从业人员而言,大部分人印象颇深的可能都是以太坊的诸多合约漏洞,EOS 公链上层出不穷的合约问题,以及少数公链漏洞信息。使用搜索引擎查找和区块链相关的审计类文章,也大多为智能合约的 checklist、智能合约的审计分析等,针对公链审计类的技术分享并无很多。这里推荐大家一份由长亭科技编写的国内首发的《区块链安全生存指南》,其中介绍了当下区块链行业环境,以及近年来区块链业内的一些著名事件等。同时分享长亭科技日前发布的《公链审计checklist》,以供公链项目开发者参考。
审计区块链公链项目,与通常的软件代码审计略有不同。通常的代码审计,我们会考虑语言特性以及该语言的 0day 或 1day 漏洞,结合常见业务场景,分析代码的实现。区块链公链项目,其本身代码量较多,在项目背后,还有严谨的金融货币模型以及共识模型,且无较为实用的审计工具,需要更多以来人工审计,审计的定制化程度高,难度及工作量大。依我理解,我们主要从以下方向入手:
语言特性及其已知漏洞
底层实现【密码学、序列化、大数运算等】
区块链基本元素的实现【区块、交易、链】
区块链行为的逻辑【生成一个区块、交易进入 tx_pool 等】
区块链的其他组件【p2p、rpc、钱包等】
共识算法合理性
金融模型合理性
历史公链漏洞
漏洞发现过程
我们在审计过程中发现的漏洞利用方式,源于该公链项目在实现 Merkle Tree 逻辑时,与常规实现方式有些许不同。在整理之前比特币区块链、以太坊区块链,出现过的漏洞时,发现了可能利用的漏洞点,经过确认发现可以影响不同节点间达成共识,进而造成分叉。
在发现问题后,长亭科技立刻汇报给公链项目方,公链开发者响应迅速,非常重视此次安全问题,即刻完成了修复。
什么是 Merkle Tree
Merkle Tree,一般也称为 Merkle Hash Tree。是数据结构中我们所了解的树,其各个节点均包含 Hash 值。
Merkle Tree 具有以下的特点:
它是一棵树,具有数据结构中,树结构的所有特点。【在讲解中我们默认其为二叉树】
Merkle Tree 的叶子节点中存放数据。非叶子节点的 value,是由其左右两子节点,经过组合和 Hash 运算获得。
让我们举个例子来表示:
我们可以看到,只有叶子节点中存放了 Data【Tx Hash】,而其上面每一个非叶子节点的 value,都是他们孩子的 value,经过组合和哈希运算得到的。
Merkle Tree 被广泛应用于对比以及验证处理。在区块链技术中,Merkle Tree 被用于验证各区块中的交易,在传输过程中是否被篡改。因为我们可以看到,倘若修改任一叶子节点的内容,这棵 Merkle Tree 的 root 节点的值【Merkle 根】就会随之改变,可以通过判断 Merkle 根来得知,该区块中,有交易可能传输出错或被恶意篡改。
审计中发现的实现方式
核心代码【有修改】:
# 外层为循环,以建立Merkle Tree
if hashList[i+1] == None :
hashList[p] = sha3(hashList[i]+hashList[i])
else :
if hashList[i] > hashList[i+1] :
hashList[p] = sha3(hashList[i]+hashList[i+1])
else:
hashList[p] = sha3(hashList[i+1]+hashList[i])
在审计过程中,当考察到 Merkle Tree 底层实现方式时,发现其实现有一定违和感,具体如下:
先根据 tx_hash 数量,建立一棵完全二叉树
将 tx_hash,按顺序放至叶子节点中
通过以下算法算得上层节点的 Hash 值:
对于某一非叶子节点,将其两孩子的 value 进行比较,序列大者靠前
将排好的两孩子,进行Hash运算,得到的 Hash 值为该节点的 value
如此往复,建立 Merkle Tree,算得根节点的 value
举例说明:
初看此处时,觉得实现 Merkle Tree 的方式有些奇怪,进行了一次两孩子的 value 比较,但想到 Merkle Tree 的主要意义在于校验,防止篡改。实现方式略有不同可能影响不大,遂只做了记录。
Bitcoin 漏洞CVE-2012-2459
在整理曾经出现的公链漏洞时,发现了这样一个有名的比特币 DoS 漏洞。
通过了 Merkle Root 的根认证的区块,但其实并不合法。可能导致区块链分叉,或是进行双花攻击等,危害性较高,攻击方式较为简单,我们来分析该漏洞成因。
在旧版本的 Bitcoin 客户端中,其实现 Merkle Tree 的建立【计算该区块交易的 Merkle 根】的过程和通常的方式没有太大区别,当区块中交易个数为奇数时,会进行一个这样的操作:
在计算 Merkle 根时,若其叶子节点的个数为奇数个,则复制最后一笔交易的 Hash 值,参与建立 Merkle Tree【并不是复制一笔交易出来,不能有重复的交易】。
看上去没有什么太大的问题,只是计算 Merkle 根时,对边界的处理。但 CVE-2012-2459 漏洞,利用的就是这一个特性。
区块A:
攻击者首先选择一个有奇数笔交易的区块,构造区块时,将最后一笔交易复制一份,加入该区块中。
区块B:
区块A是一个正常的区块,区块B是拥有重复交易的区块。在共识过程中,会因为 tx_3 和 tx_2 一致,而造成出错并抛弃。但这两个区块根据上面的描述,对应的 Merkle 根是一致的。对应的区块头也是一致的。
攻击者可以构造同样的区块头,在传播广播区块时,广播不同交易列表的区块信息,导致网络中接收到原区块的节点认为此区块有效,接收到恶意区块的节点认为此区块无效,造成不同节点面对这一区块不能达到共识,进而使区块链分叉,或是进行双花攻击等,危害极大。
漏洞利用方式
回到我们的审计过程中,类似上面的例子,思考在此项目中是否也会有类似的攻击手法。
我们发现,对于任意两笔相邻的交易,我们可以调换他们的位置,来使 Merkle 根不变,更有甚者,我们可以交换任意一个节点下,两个孩子为根的树的位置,也不会改变 Merkle 根的值。
经过对于其他部分对区块和交易的校验分析之后,我们发现可以通过构造两笔特定的交易,造成和上面比特币区块链类似的攻击效果。经过攻击链的设计和验证后,验证了此方法的可能性。此公链在运行过程中,有可能因此漏洞,被进行强制分叉或是双花攻击等。
总结
汇报该漏洞后,公链项目方十分重视这一问题,响应迅速,立刻修复了该实现问题。
在审计该项目的一些底层实现过程中,我们审计到这个较为经典的漏洞,并根据此漏洞,构造了一条完整的攻击链,达到了对公链强制分叉的影响。这也提醒了我们: 代码千万行,安全第一行。实现不规范,首席两行泪。
对于已证明安全的密码学方案或技术方案,若实现不规范,亦有可能成为漏洞,造成严重后果。
- 上一篇:梦想成真女子梦到中奖买彩票果真中120万人民币
- 下一篇:优盈【优品盈天下】