前言
背景
在现代软件开发环境中,开发团队经常会依赖于开源的第三方组件来节省时间和提高效率。这些组件本身是由开源社区(Github、Gitee)贡献者来开发,然而,这也带来了一些潜在的安全风险,特别是涉及到供应链安全(这些组件的开发者队安全队安全方面的了解几乎为0、恶意的供应链投毒风险)和第三方组件的质量问题(存在抄袭、开源许可证合规风险)。
SCA概述
SCA(Software Composition Analysis)译为软件成分分析,通俗的理解就是通过分析软件包含的一些信息和特征来实现对该软件的识别、管理、追踪的技术。SCA技术能够有效帮助使用者发现开源组件中的安全性问题。SCA主要有三种用例:开源漏洞管理、开源许可证管理以及SBOM清单。
功能组成
- SBOM清单:SCA工具通常从扫描开始,生成产品中所有开源组件的清单报告,包括所有直接和间接依赖关系(当前项目使用到的开源软件成分)。掌握所有开源组件的详细清单是管理开源使用的基础
- 合规问题-开源许可证管理:许可证相关的风险提示,主要针对高风险协议(例如GPL等)进行提取
开发人员经常在软件中引入开源片段、函数、方法和操作代码。因此,软件代码中经常会包含各种声明不同许可证的子组件。这些子组件的许可证条款和条件与项目整体主许可证的条款和条件冲突,就可能产生许可证合规风险 同源代码检测,主要用来识别因代码抄袭带来的合规问题
- 识别安全漏洞:主要识别开源软件中存在的漏洞、影响范围、风险等级等,漏洞响应,基于识别到的开源成分,在漏洞批漏的情况下,快速响应和修复漏洞
工作原理
漏洞的收集:例如爬去NVD、CVE等缺陷批露平台上面的数据,汇总成自己的漏洞数据库 漏洞的查询:根据用户的软件生成的SBOM信息,到漏洞数据库查询漏洞数据,汇总成缺陷报告,提供给用户 缺点:大部分漏洞检查部分,都还没有基于漏洞的可达性分析,导致相关报告中存在较多的误报
软件供应链漏洞检测通用架构
SCA工具的原理是通过扫描目标系统中的所有组件成分、引用依赖关系、版本等信息,与多个漏洞数据库进行匹配,包括国家信息安全漏洞共享平台(CNVD)、国家信息安全漏洞库(CNNVD)、National Vulnerability Database(NVD)等,达到匹配及识别漏洞、许可证合规等风险的效果。影响SCA代码分析准确性的因素主要分三个方面:其一是SCA工具支持组件的数量和检测算法,其二是应用程序引用开源组件的方式,其三是底层漏洞库的广度和颗粒度。
组件的数量和检测算法方面
SCA根据样本组件特征来匹配被测程序中的特征,从而判断应用程序是否引用该组件,因此,支持组件的数量越多,检测率也就越高,支持的组件数量越少,越会导致检测遗漏;另外,检测算法和特征设计是否合理也直接影响到分析的准确性和分析效率,对此,不同SCA工具厂商有不同的解决方案。
基于包管理器(构建)检测技术
多数SCA工具都是基于包管理器相关技术,来获取相关的开源依赖。并且当前大部分的语言,都有第三方库的管理和配置功能
Java:maven、gradle、ant、bazel Js/Ts:npm、yarn Go:mod Rust:cargo Python:pip PHP:Composer Ruby:Gem、Bundler
基于这些包管理器,可以方便地获取第三方依赖信息,更进一步来说,可以获取到传递依赖信息等。所以这种方式是目前应用非常广的一种技术。当然,该方式也有很多的问题,在一些情况下,可能会导致获取不准确:
依赖关系复杂 传递依赖时,涉及到多版本的决策实现 传递依赖中,在当前项目中未使用的开源组件识别
当然,这些是使获取的开源组件更加准确的需要,是在完成基础功能之上,进行优化的策略 基于源码的相似度匹配,最重要地是对已知第三方库的代码创建指纹代码,以方便后面的对比操作,目前,从理论上,主要的代码指纹建立的方式有:
- 直接将源码当作自然语言构建
- 基于Token的构建
- 基于操作符的构建
- 基于AST的构建
- 基于CFG的构建
- 基于CPG的构建
- 基于程序切片等
有那些检测算法?
哈希匹配算法: 这是最基本的算法之一,它通过比较组件的哈希值来检测应用程序中的组件引用情况。如果两个组件的哈希值相同,则可以确定它们是同一个组件,从而判断应用程序是否引用了该组件。 字符串匹配算法: 这种算法通过扫描应用程序的源代码或二进制文件,搜索特定的字符串或标识符,以确定是否存在对特定组件的引用。例如,可以搜索组件的名称、版本号或其他标识符。 语法分析算法: 这种算法会对应用程序的源代码进行语法分析,识别其中的依赖声明或导入语句,从而确定应用程序是否引用了特定的组件。这种方法通常用于识别编程语言特定的依赖关系。 语义分析算法: 与语法分析类似,但更进一步,它不仅考虑语法结构,还考虑语义信息,例如函数调用关系、类继承关系等。这种算法可以更准确地识别组件之间的依赖关系。 机器学习算法: 一些高级SCA工具可能会利用机器学习技术,通过对大量已知应用程序的分析和训练,来识别和预测应用程序中的组件引用情况。这种方法可以提高检测的准确性和效率。
引用开源软件的方式方面
应用程序在引用开源软件时,不同的应用程序即使引用同一个组件也存在引用不同的功能,引用功能的多少也各不相同,这样带来的结果就是在应用程序中包含该组件的特征数量也是大小不同的,引用功能多包含的特征一般也多,引用的功能少,则包含的特征也少。而应用程序包含组件特征的多少直接影响到SCA工具的检测的准确性,组件特征越少,SCA工具检测越困难,因此即使两个不同应用都引用了相同组件,可能一个应用可以检测到,另外一个应用则无法检测出该组件。这种场景对SCA工具检测二进制文件尤其明显。
漏洞库的积累与颗粒度
- 数据收集和整合: 不仅要依赖官方漏洞公开渠道,还可以通过其他途径,如安全研究团队、漏洞报告平台、安全厂商的研究报告等,收集更多的漏洞信息。同时,还可以利用漏洞扫描工具、漏洞情报服务等自动化工具来增加数据源。
- 丰富化的描述信息: 漏洞描述应该包括漏洞的影响范围、攻击场景、利用难度等信息,以便帮助用户更好地理解漏洞的严重性和影响程度。
- 关键影响组件信息: 对于涉及多个组件或依赖的漏洞,需要清楚地标识出关键的影响组件,以便用户更准确地评估漏洞的风险和优先级。
- 漏洞影响分析: 提供漏洞的影响分析报告,包括漏洞可能导致的具体危害、潜在的攻击场景和利用方式等,以帮助用户更全面地理解漏洞的风险。
- 修复方案建议: 对于已知漏洞,提供相应的修复建议或解决方案,包括安全补丁、临时性的解决方案、配置调整等,以帮助用户更快速地解决问题。
- 漏洞分类和标签: 使用标准的漏洞分类系统和标签,帮助用户更容易地对漏洞进行分类、过滤和搜索,提高漏洞库的可用性和易用性。
SCA产品
- Black Duck by Synopsys(现在被称为“Black Duck Binary Analysis”): 一款知名的商业SCA产品,可以扫描软件项目中使用的开源组件,识别其许可证和潜在的安全漏洞,并提供相关建议和解决方案。
- Nexus Lifecycle by Sonatype: 一款常用的商业SCA产品,它提供了全面的开源组件管理解决方案,包括漏洞管理、许可证合规性、安全审查等功能。
- WhiteSource Bolt: 一款适用于开发人员的免费SCA工具,可以集成到常见的集成开发环境(IDE)中,帮助开发人员及时发现和解决软件项目中的开源组件安全问题。
- Dependency-Check 是一个开源的软件组件漏洞扫描工具,用于检查应用程序的依赖项(如库、框架等)是否包含已知的安全漏洞。
- Snyk: 一款集成了开源组件安全扫描和开发人员工作流的平台,提供了漏洞扫描、依赖性分析、许可证合规性等功能。
- 墨菲安全、开源网安、默安科技、悬镜安全、中科天齐、synopsys
Depency-Check
基本介绍
Dependency-Check 是 OWASP(Open Web Application Security Project)的⼀个实⽤开源程序,⽤于识别项⽬依赖项并检查是否存在任何已知的,公开披露的漏洞。 ⽬前,已⽀持 Java、.NET、Ruby、Node.js、Python 等语⾔编写的程序,并为 C/C 构建系统 (autoconf 和 cmake)提供了有限的⽀持。⽽且该⼯具还是 OWASP Top 10 的解决⽅案的⼀部分。 Dependency-Check具有命令行界面,Maven插件,Ant任务和Jenkins插件。核心引擎包含一系列分析器,这些分析器检查项目的依存关系,收集有关依存关系的信息(在工具内称为证据)。然后,将证据用于识别给定依赖项的通用平台枚举(CPE)。如果标识了CPE,则会在报告中列出相关的常见漏洞和披露(CVE)条目的列表。其他第三方服务和数据源(例如NPM Audit API,OSS Index,RetireJS和Bundler Audit)用于特定技术。
工作原理
Dependency-Check通过收集有关其扫描文件的信息(使用分析器)来工作。收集的信息称为证据,收集了三种类型的证据:供应商,产品和版本。例如,JarAnalyzer将从Manifest,pom.xml以及扫描的JAR文件中的包名称中收集信息,并且具有启发式方法,可以将来自各种来源的信息放入一个或多个证据桶中。
文件类型分析器
Dependency-Check包含多个文件类型分析器,用于从分析的文件中提取标识信息。
工具使用体验
Maven插件集成:Dependency-check-maven
代码语言:javascript复制 <groupId>org.owasp</groupId>
<artifactId>dependency-check-maven</artifactId>
<version>9.1.0</version>
</dependency>
<plugin>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-maven</artifactId>
<version>7.0.4</version>
<configuration>
<autoUpdate>true</autoUpdate>
</configuration>
<executions>
<execution>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
Dependencies Scanned: 160 (128 unique) Vulnerable Dependencies: 47 Vulnerabilities Found: 143
优点:分析输出的漏洞更多 准确率更高 缺点:不支持开源许可证检测
CLI方式-安全人员检测
代码语言:javascript复制dependency-check --project test -s "/xxx/tianxuan-secflatform.jar" -o /xxx/test
优点:在没有源码的情况下,直接使用Jar包进行代码安全检测 缺点:与Maven插件相比同一项目输出的漏洞结果更少
Dependencies Scanned: 151 (126 unique) Vulnerable Dependencies: 34 Vulnerabilities Found: 109
CI集成-Jenkins插件:Dependency-Check
该插件具有执行依赖关系分析和构建后查看检查结果的功能。
一些问题
Maven插件对多模块依赖项目 支持不太友好 可能是我配置问题
snyk
基本介绍
Snyk是一套云原生、以开发人员为中心的工具,专为DevSecOps和云原生开发商店而构建。它以其SCA和容器安全扫描功能而闻名,能够扫描应用程序的依赖文件,包括开源库和框架,以检测其中是否存在已知的漏洞。它使用多个漏洞数据库,包括NVD(National Vulnerability Database)和自有的漏洞数据库,来匹配组件版本与已知漏洞之间的关联。它还提供与常见集成开发环境(IDE)的集成,如IntelliJ IDEA、VS Code和Eclipse等,通过这些插件,开发人员可以在编码过程中即时获取组件漏洞信息,从而更好地集成安全性和及时修复漏洞。同时提供了命令行工具,可以方便地集成到CI/CD流程中,实现自动化的漏洞扫描和报告生成。
工作原理
分析依赖性:Snyk 会扫描项目中的依赖项,确定项目使用的所有库和模块。这包括直接依赖项和间接依赖项(即这些库所依赖的库)。 与漏洞数据库对比:Snyk 将扫描结果与其维护的漏洞数据库进行对比。这个数据库包含了公开的安全漏洞,以及根据其威胁级别进行分类的信息。 识别和报告漏洞:如果在依赖项中发现漏洞,Snyk 会生成报告,指出存在的问题和漏洞的严重程度。这份报告将帮助开发人员识别和评估项目中的安全风险。 提供修复建议:Snyk 不仅指出了漏洞,还提供了解决方法。这可能包括升级到较新版本的库,应用补丁,或者更换到没有漏洞的其他库。 集成和自动化:Snyk 可以与开发工具链和持续集成/持续部署 (CI/CD) 流程集成,以确保在开发和部署过程中自动进行安全扫描。这样可以及时发现并处理漏洞,降低项目安全风险。 监控和持续保护:除了初次扫描,Snyk 还会持续监测项目,以确保新发现的漏洞能够及时通知开发人员,并采取必要的措施。
工具使用体验
Maven插件集成:Snyk Security
Open Source - 69 unique vulnerabilities: 7 critical, 27 high, 28 medium, 7 low
优点:支持对容器镜像检测 缺点:用户升级依赖还需要一个版本一个版本手动修改,修复比较繁琐
CLI方式:snyk test
代码语言:javascript复制Tested 132 dependencies for known issues, found 69 issues, 69 vulnerable paths.
snyk test --json >> snyk_report.json
优点:1、检测速度快 2、扫描结束后会邮件提醒 缺点:1、检测出的漏洞不够多 2、不支持html导出 只支持json导出 3、用户升级依赖还需要一个版本一个版本手动修改,修复比较繁琐
Maven Dependency Checker
优点:1、操作起来简单 2、因为只是发现过时依赖版本,分析速度快 缺点:1、只是简单的提示升级为最终版本,没有考虑到依赖版本兼容性问题(最新版可能不是稳定版本) 2、用户升级依赖还需要一个版本一个版本手动修改,修复比较繁琐