1. 引言
当谈到区块链的时候,往往会涉及几个关键词:“不可伪造”、“全程留痕”、“可以追溯”、“公开透明”、“集体维护”等,给人的第一印象就是安全。区块链的各个区块之间通过随机的哈希算法实现连接,后一个区块包含前一个区块的哈希值,随着信息交流扩大,一个区块与一个区块相连,形成的结果就是区块链。根据区块链的51%算力攻击法则,只要不能掌握全部区块数据节点的51%,就无法随意操控和修改网络数据,这使得区块链本身变得相对安全,避免了主观、人为的数据变更。这也就是为什么我们说区块链相对安全的原因。我们从理论上解决了区块链的安全问题。那与区块链相关或者基于区块链技术 [1] 进行开发的项目就真的安全了吗?解决了区块链底层技术的安全性问题后,区块链项目安全问题就回到了软件系统设计自身的层面了。
生活中大家时刻与软件系统打交道,无论是普通用户,技术研发人员,学术研究人员,都在使用着软件系统。计算机软件技术发展给我们带来便利的同时,也带来了许多安全隐患。大多数时候,安全隐患问题更多的是交由学术研究者和技术研发人员来控制。这些安全隐患对于大多数普通用户来说,往往并没有那么容易感知,但是如果在软件设计过程中研发人员忽略了安全隐患带来的风险,引入了漏洞,那么软件漏洞带来的危害(如个人隐私信息、财产安全等)将由用户承担。各种网络安全事件频发,严重危害了网络的进一步发展和用户对其的信任度。软件系统作为互联网时代的重要组成部分,其本身在编码时期由于开发和设计不良引起的问题所产生的漏洞是导致不法分子攻击的根本原因。
本文针对开源社区(GitHub社区)中交易场景下的区块链相关的项目的漏洞情况展开分析研究。基于Scantist SCA (Software Composition Analysis)对项目的漏洞情况、漏洞修复问题进行检测。
2. 研究问题
根据上述引言可知,本研究的目的是通过针对交易场景下的区块链项目 [2] 进行分析。基于SCA工具,将开源社区中漏洞情况进行分析,帮助开发人员在进行相关开发时,提高安全编码的意识,更好的对项目进行漏洞分析及修复。
我们提出以下研究问题:
1) 区块链项目在交易场景下的第三方组件漏洞现状如何?
2) 第三方组件漏洞修复可达性如何?
3. 数据收集与筛选
3.1. 数据收集
数据收集是利用Python中的request库,编写GitHub通用爬虫程序。其主要工作原理是:请求访问GitHub的API。通过API获取到每个项目的URL链接,再进行内容解析,通过解析结果将数据存入CSV中,待后续进行筛选。爬虫算法如图1所示。
通用爬虫程序编码完成后,对GitHub进行关键词检索,由于GitHub中没有对交易场景下的区块链项目进行专门分类,所以数据集的获取需要自行采集。通过尝试阶段对区块链相关关键词进行检索。将检索后的结果,进行人工筛选出有价值的,符合研究目标的关键词进行重新检索,如Bitcoin Payment,Ethereum Transaction等。在此基础上我们一共收集了3290个项目,等待二轮的数据筛选。
3.2. 数据筛选
3.2.1. 需要筛选的原因
在数据收集阶段,我们爬取了与区块链相关的项目3290个。由于区块链本身的项目数量十分庞大,并且语言繁杂,这给代码安全分析带来了很大的挑战,目前大部分SCA工具支持的都是主流语言,所以一些小众的语言并不适合代码安全检测。我们在筛选的时候,选取主流且具有代表性的语言Java和JavaScript作为项目扫描的主要对象。除了主流语言的筛选之外。主题的选择十分重要,区块链的应用场景十分广泛,如贸易,物流,文娱,金融交易,社交,知识产权,工业等场景,其应用成熟度也是不一样的。在金融交易场景下的应用成熟度是目前来说最高的。所以我们选择对金融交易相关场景进行开源项目的代码安全分析。筛选过程需要对一些主题不适合的区块链项目进行剔除,我们选择通过手工筛选的方式对3290个项目进行二轮筛选。最后保留下来了153个项目。
3.2.2. 手工筛选的意义
交易场景下的项目的定义比较宽泛,而且GitHub社区并没有单独为交易场景建立明确的主题,所以需要我们制定一些标准,对较为符合我们主题的项目进行保留。手工筛选的过程能够让项目的匹配度更加契合主题,使最终代码安全的分析更加符合分析的领域。有些项目由于各种原因,在GitHub上已经弃用、停止维护,显然这些项目是不符合我们的需求的。
在筛选过程中通过项目主题契合度、是否适合扫描、维护程度、流行度、活跃程度五个维度建立筛选模型,如图2所示。

Figure 1. The crawler algorithm implementation process
图1. 爬虫算法实现流程
在通过建立检索模型后进行手工筛选,我们发现一些类型与交易场景息息相关。例如在Bitcoin Payment中:实时加密货币价格跟踪器、比特币电子钱包、比特币支付网关、支付监听器、比特币支付处理系统、比特币现金和莱特币支付机器人、密钥管理服务等项目。又例如Ethereum Transaction中:以太坊交易管理器、以太坊支付二维码生成器、以太坊交易跟踪库等项目 [3],与交易场景密切相关的项目是符合作为候选条件的。
4. 研究问题与结果分析
在研究问题之前,我们对SCA工具做了一个分析,来了解SCA工具在漏洞检测中有哪些能力,在4.1中我们分析了以Scantist SCA为例,分析了SCA工具通过哪些指标来帮助分析漏洞的情况。4.2~4.4中我们对研究问题进行了探究。
4.1. SCA工具指标分析
不同的SCA工具对漏洞扫描结果有着不同的呈现方式,只是侧重点会有所不同,并且增加除扫描以外的辅助功能,以帮助漏洞修复。
Scantist SCA [4] 提供了多个指标来帮助对依赖项中的漏洞进行风险评估,我们根据扫描报告,将这些指标分为四类,以帮助进行评估。
1) 基于代码分析的指标:Scantist SCA工具可以分析源代码或二进制文件及代码片段,以推断依赖项的使用情况,可应用于编译与未编译的项目。
a) 对于未编译的项目会进行Air Gap扫描(预测扫描)。通过直接依赖或项目环境,推测间接依赖。间接依赖由依赖图谱预测,获得的是项目依赖的近似值,这种方式是通过预测手段获取,在某些情况下可能无法达到0%误报。
b) 对于编译过后的项目,会生成完整依赖树,扫描编译过程中的环境依赖树内容。相比于未编译扫描,其优点是依赖树信息完整且正确,并且可达致0%误报结果。只是项目编译过程可能比较耗时。
我们对扫描方式做了结果对比,以确保项目扫描的准确性,如图3所示,编译过后的项目可以将整个依赖树更加完整的显示出来,不会出现漏报或者误报情况。
2) 基于组件的指标:作为依赖项使用的第三方组件,本身的特征可以代表与之相关的风险。每个组件可以找到它的历史版本信息,当前项目中使用的版本以及每个组件对应的漏洞详情。
3) 基于依赖特征的指标:依赖关系的范围和深度与它在应用程序中包含的漏洞的风险有关。依赖关系的深度越深,意味着间接依赖(可传递依赖项)越多。依赖追踪就越清晰。依赖树信息就越完整且正确。
4) 基于安全漏洞的指标:漏洞本身的特征可用于评估风险,从漏洞本身可以分析出该漏洞的详细信息。每个漏洞,都可以找到其完整的漏洞依赖关系,并根据漏洞对应组件,找到其当前版本和补丁版本,进一步计算出修复兼容性。除此以外CVE信息可以根据CVSS进行评分,即通用漏洞评分系统。它是一个行业公开标准,其被设计用来评测漏洞的严重程度,并帮助确定所需反应的紧急度和重要度。得分在0.1~3.9之间的通常被认为是低风险漏洞,得分在4.0~6.9之间的是中等风险漏洞,得分在7.0~8.9之间的漏洞是高风险漏洞,得分在9.0~10.0之间的则是超高风险漏洞。

Figure 3. Comparison of compiled and uncompiled dependencies
图3. 编译与未编译依赖对比
4.2. 交易场景下的区块链项目中第三方组件漏洞现状分析
目的:交易场景相关的项目是对安全要求比较高的领域,其处于整个交易的核心位置,如果无法保证交易的安全性,那么可以遇见的灾难是交易金额错误,交易系统崩溃等一系列问题 [5]。扫描结果的量化分析,能够对当前领域的情况进行一个全局性的概述,帮助相关开发人员提高安全的认知。本节通过平均漏洞数、高频组件、漏洞评级等角度来揭示社区中当前漏洞的现状。
方法:对筛选后的项目进行预编译,Java项目通过Maven,Gradle包管理工具对pom.xml,build.gradle文件进行编译,JavaScript项目通过npm工具对package.json文件进行编译,以此构建其依赖树。预编译的依赖树结果见图4,未编译的依赖树结果见图5。最终将获得的依赖树提供给Scantist SCA进行扫描编译过程中的环境依赖树内容。
并非所有的开源项目都能够构建成功,经过图4、图5对比发现,进行预编译后的项目可以在本地获取完整的依赖树。未编译项目无法获取完整的依赖树,只能通过Scantist SCA提供的依赖图谱(即Air Gap模式),来进行预测。为了消除这类因未构建完成,只是通过预测产生的结果带来的影响。对构建失败的项目,进行手工修复了失败项目。预编译的扫描结果见图6。
4.2.1. CVE安全漏洞数
当获得了扫描结果后,对CVE安全漏洞进行统计学加权平均数方法,以此来展示扫描的153个项目中,包含的平均CVE安全漏洞数。每个项目所包含的组件数不同,可以统计出单个项目包含最小组件数为1个,最大组件数为2069个。全部扫描的153个项目中包含总组件数为13,912个,根据这一结果可以计算其“权”。
平均CVE安全漏洞数通过以下公式计算:
其中,
是每个项目的权值,
是每个项目漏洞数。
根据计算并统计结果得出,平均每个软件项目存在21.17个已知开源软件漏洞。这一结果可以让我们清晰的看到,在区块链项目中,漏洞是普遍存在的。尽管交易场景下区块链项目的漏洞数比奇安信《2021中国软件供应链安全分析报告》中指出的“国内企业平均软件项目存在66个漏洞”的总数低,但就交易场景下的区块链项目漏洞数是无法接受的。
4.2.2. 安全等级
除了开源社区平均CVE安全漏洞数结果外,本节更加细化的将漏洞进行安全等级划分,划分依据来源于CVSS评分系统,如表1所示。
将154个项目中扫描出的3240个CVE安全漏洞和2929个安全隐患,按照CVSS评分表,进行四个安全等级分类。安全隐患分析如图7所示,CVE安全漏洞分析如图8所示。
其中安全隐患的漏洞数据来源于源代码的修改日志,漏洞追踪和安全报告。

Figure 8. CVE security vulnerability analysis
图8. CVE安全漏洞分析
CVE安全漏洞数据来源于NVD,指的是已发现的CVE安全漏洞。
从安全隐患的角度和CVE安全漏洞的角度对比可以发现低风险和超高风险的比例相对来说低一些,但中等风险和高风险仍然占据了区块链项目的绝大部分比例。这也反映出与交易相关的区块链项目的安全情况有待提升。
4.2.3. 公共的漏洞
本小节通过将项目扫描结果按照组件进行归类,目的是找到各个项目中公共使用的组件,并通过公共的组件找到这些公共的CVE安全漏洞。一方面可以说明这些CVE安全漏洞在区块链项目 [6] 中影响较广,另一方面也为后续漏洞的修复提供了可能性。
我们归类了所有项目中共同使用的前20个组件,组件归类见表2。
当通过扫描结果获得公共组件后,便可以依据公共组件来找到对应的CVE漏洞。需要注意的是,有时候一个组件会对应多个CVE漏洞。具体对应关系如表3所示。

Table 3. Correspondence table between components and vulnerabilities
表3. 组件与漏洞对应关系表
通过表2容易发现,项目共同使用的组件的功能往往趋向于基础工具类模块,如路径解析模块、文件解压缩模块、程序调试模块、读写文件模块等。这种基础性的组件,不仅仅在区块链领域频繁使用,可以预见的是,在开源社区中其他项目中也是会被广泛使用。
通过表3不难发现,这类组件对应的CVE安全漏洞,其危险程度往往在中等风险或高风险。影响数目广,亟需给出解决方案,修复漏洞。
4.3. 第三方组件漏洞修复分析
目的:在4.2.3节,我们对公共组件漏洞情况进行了分析,找到了项目中公共使用的组件,并发现这些组件往往影响的项目数都在几十个不等,这意味着一旦修复了这些高频使用的组件,那对整体的安全性的帮助将是巨大的。本节通过案例研究使我们深入了解组件以及漏洞修复情况。
4.3.1. Scantist SCA进行漏洞推荐修复
Scantist SCA具有扫描后对漏洞进行推荐修复的能力,即给含有漏洞的组件提供修复建议,并根据需求进行安全替换 [7]。其工作原理是:根据扫描找到项目中包含的组件,一个组件往往包含多个CVE漏洞。Scantist SCA会去漏洞数据库对组件进行匹配,数据库中包含该组件的所有版本信息。从中可以找到不含漏洞的组件版本,我们根据当前使用的组件版本与无漏洞版本进行对比,最终对组件进行修复并计算出修复后的兼容度。组件信息如表4所示,推荐修复情况如表5所示。

Table 4. Take the component Lodash as an example
表4. 以组件Lodash为例
从表4中很容易看出,Lodash组件在早期版本中,持续被爆出CVE漏洞,但是到了4.17.21版本就不含漏洞了,所以对于该组件,可以将其版本更新为4.17.21。但是需要注意的是,组件的版本修改后,会出现不匹配的问题。在表5中的Fix Compatibility中会提示修复兼容性。对于修复兼容性高的组件,修复后往往不会出现问题。而对于修复兼容性低的组件,可能会出现修复后程序无法编译现象,所以对于此类问题,需要我们在修复漏洞后做一个兼容性问题检查。
4.3.2. 修复兼容性分析
我们从扫描的项目中选取了10个具有代表性的项目进行漏洞修复后的代码兼容性验证,这些项目平均包含50+个漏洞。在筛选完项目后,通过Scantist SCA进行推荐修复。
对修复后的项目进行了重新编译,观察修复后的项目是否可以继续使用。结果表明,9个项目修复后的项目中正常使用,不受组件修复的影响,即高兼容度。但仍然有1个项目修复后会出现无法编译通过的情况,即组件修复不兼容的情况。
基于此,对剩余的无法编译的项目进行分析,最终发现当含有漏洞组件版本号与无漏洞版本号差距很大时,比较容易出现不兼容现象,因为无漏洞版本的API发生了改变,导致使用无漏洞版本的组件后,出现无法识别现象。这种情况下,对程序的代码进行重构,使新编写的代码能够与新的组件兼容 [8]。
随后,再次扫描修复后的项目,发现所有项目中的组件都不包含漏洞问题,并且可以正常使用。经分析,可以得出结论,通过Scantist SCA对项目进行组件成分分析后,可以发现一个项目中包含的漏洞,并且根据组件情况,进行漏洞修复,最终保证区块链项目的安全。
5. 讨论
经过上述的分析,我们发现开源社区中的区块链项目或多或少都存在安全问题 [9]。面对如此庞大的漏洞情况,用SCA工具检测是十分有必要的,在经过SCA工具的检测以及修复后,可以将有安全漏洞的项目变成不含漏洞的项目。虽然我们也可以等开发过程结束后,进行漏洞测试,再进行修复,但这样的方式是一种亡羊补牢的方式,它会引入向后兼容性的风险,因为不同版本的第三方组件作用会有细微差异,这就引入了兼容性的问题,我们往往还需要将修复后的代码进行简单的重构。
面对这个问题,我们可以在项目开发初期,就将安全防护嵌入开发,为实现这一点,最好的方式是实施安全防护左移策略。安全防护“左移”就是将安全防护尽可能地移到开发流程的早期。比如在开发流程的早期,还在确定选择哪些第三方组件作为开发需要的组件的时候,就可以使用SCA进行安全扫描,将有问题的组件替换成相同或者无安全问题的版本。这样就确保开发过程中使用的组件始终是安全的。在开发中期如果需要引入新的组件,可以再次进行安全评估,以保证整个开发过程的安全性。安全防护左移不仅有利于降低网络风险,还可以降低成本。IBM研究院发现,在设计过程中解决安全问题,比在实施过程中解决的成本要低六倍。
6. 总结和展望
6.1. 本文总结
本文主要分析和研究了开源社区中区块链项目的漏洞情况。本文提出了一个基于Scantist SCA的漏洞扫描方法。该方法基于一个基本事实:目前区块链技术发展迅速,大家关注点在区块链理论的安全性。但是很少对基于区块链进行开发的项目的安全性做一个系统性的现状分析,尤其是交易场景下的区块链项目。我们对这些项目的安全性情况不了解,但是却离不开这些项目,如比特币电子钱包,比特币支付处理系统等。由此,我们主要做了两个方面的研究。
第一个方面是GitHub社区中区块链项目的整体情况分析。我们通过统计方法计算了平均每个项目的漏洞情况,并对项目中漏洞的风险等级做了评估,最后也找到了该领域的项目公共组件的漏洞情况。
第二个方面是根据推荐的修复统计了修复率,并尝试使用SCA工具对漏洞进行修复。对不能通过推荐修复的漏洞,提出了修复办法。
6.2. 未来工作展望
虽然我们对区块链项目的代码漏洞情况进行了分析,但是仍然存在不足之处。未来将针对不足之处展开分析:
1) SCA工具是否可以除了建议修复选项外,同时对向后兼容的风险进行解释。先前的工作发现,开发人员害怕破坏原有的组件结构是他们不想更新易受攻击的依赖项的主要原因之一。我们可以进行更深入地分析,以了解依赖项中的某个版本更改会导致哪些代码更改,以及它如何影响依赖项应用程序。
2) 开发人员如何响应来自SCA工具的警报也不在本次研究的范围之内。类似的,是什么导致依赖性漏洞误报是一个开放的研究问题 [10],超出了本研究的范围。当前我们进行案例研究,以调查开源社区中区块链项目的漏洞情况和漏洞修复后给社区安全性带来的提升为目的。未来开发人员对SCA工具的响应情况还可以做进一步研究。
基金项目
本研究得到国家自然科学基金面上项目资助,项目编号为61972359;得到浙江省自然科学基金一般项目资助,项目编号为LY19F020052。
参考文献
NOTES
*通讯作者。