前言
随着 DevSecOps 概念的逐渐推广和云原生安全概念的快速普及,研发安全和操作环境安全现在已经变成了近两年行业非常热的词汇。在研发安全和应急响应的日常工作中,每天都会收到大量的安全风险信息,由于目前在系统研发的过程中,开源组件引入的比例越来越高,所以在开源软件治理层面需要投入很多精力。但是由于早期技术债的问题,很多企业内部在整个研发流程中对使用了哪些开源组件,这些开源组件可能存在严重的安全隐患等相关的问题几乎是没有任何能力去收敛,所以多年前的 SCA(Software Composition Analysis 软件成分分析)技术又重出江湖,变成了这一部分风险治理的神器。本文主要探讨的范围是利用 SCA 技术实现对开源组件风险治理相关能力的建设与落地。
SCA 概念其实出现很久了,简单来说就是针对现有的软件系统生成粒度非常细的 SBOM(Software Bill of Materials 软件物料单)清单,然后通过风险数据去匹配有没有存在风险的组件被引用。目前市面上比较出色的商业产品有 Synopsys 的 Blackduck 、Snyk 的 SCA 、HP 的 Fortify SCA 等,开源产品有国内悬镜的 OpenSCA 。但是通过对这些产品的调研和分析后发现,这些产品由于诸如风险数据库完整度、与现有研发流程耦合程度、性能和社区支持不完整等原因,不能很好地融入企业内部的研发流程,但是这一部分能力在企业内部对于SDL工作而言又是不可或缺的能力。所以企业内部的信息安全团队需要结合业务团队的需求,安全团队自身对于风险的理解,企业内部的研发流程现状和现有的技术与数据能力、应用成本和 ROI 等现状和问题进行综合考虑,打造自己的 SCA 能力,从而帮助业务团队多快好省地解决软件供应链层面上的信息安全问题,安全团队也可以更好地对组件风险问题进行全局视角下的治理。从上面的内容大家也许听出来了,在企业内部建设 SCA 能力的过程中会涉及到很多的产品和运营方面的问题,诸如跨部门协作、系统稳定性、业务和安全部门对于风险的定义不一致等问题。本文主要介绍 SCA 能力在企业内部实际落地的过程、遇到的问题以及对 SCA 技术的看法和展望,旨在为业界提供一个可以参考的解决方案和范本。
安全视角下的研发风险
在企业内部的信息安全团队看来,很多企业内部实际上在整个研发流程当中遇到的风险面实际上是蛮多的,通过对于各种攻击面的梳理和分析之后,实际上在研发流程中被经常提及的风险主要包含以下三类。
通用漏洞风险
在组件安全层面上,首先遇到的问题,也是最容易发现的问题就是漏洞问题,造成的影响也十分直观,可以导致系统因为恶意的利用导致出现非预期的功能,进一步破坏系统的完整性和可用性。根据 2021 年 Synopsys 放出的软件供应链相关的数据显示,开源代码仓库中至少存在一个漏洞的仓库占整体开源仓库的比例从 2016 年的 67% 上升到了 84%,至少存在一个高危漏洞的代码仓库占全部仓库的比例从 2016 年的 53% 上升到了 60%,最高的时候是 2017 年,这一数字是 77%。
而根据 2020 年 Snyk 发布的另一份开源组件与供应链安全的报告显示,漏洞的数量仍然需要提高警惕,XSS 漏洞仍然占据数量榜首,紧随其后的是命令执行类漏洞,这些漏洞会严重影响系统的稳定性。
在上述所罗列出来的风险当中,当注意力集中到恶意包(Malicious Packages)上时,我们可以发现该类型的风险是 2019 年度上升幅度最快的威胁之一,这也引出了下面的问题。也就是软件供应链相关的风险。
供应链相关的风险
开源组件的生产-构建-发布过程其实是与企业内部常规的系统研发上线的流程是一致的,简单来说可以抽象成下图中的样子:
开源软件作者完成代码编写后 push 到源代码管理平台(GitHub、码云、Gitlab私服平台)等,然后在 CI/CD 平台上发起构建编译打包的流程,在这个过程中,CI/CD 平台会从组件依赖平台(Sonatype Nexus 私服或是 MVNRepository 官方源)上获取需要依赖的包,在 CI/CD 完成打包/镜像封装过程后,通过项目分发平台分发到生产环境上,更为现代的方法是直接拉取 Docker 镜像做部署,完成系统的上线。
这个过程看似简单,但是实际上环节还是有不少的,我们把每个环节拆解来看,实际上每个环节都是会有很多风险的,如下图所示:
IDE 插件投毒:为了更高效率地开发软件,开发人员往往会在自己的IDE当中引入各种各样的插件来提升自己的开发体验与效率。这个是一件非常正常的事情,但是往往软件开发人员没有足够的安全意识,导致自己的IDE中可能会安装了一些有问题的组件,甚至 IDE 本身也出现了供应链投毒的情况,这种 case 多到数不胜数,比较出名的是2021年5月份 Snyk 披露的一份安全报告中显示攻击者在 VSCode 的插件市场发起了投毒行为,一些有问题的扩展是“LaTeX Workshop”、“Rainbow Fart”、“在默认浏览器中打开”和“Instant Markdown”,所有这些有问题的扩展累计安装了大约 200 万次,此次事件所造成的影响是非常广泛的。
提交缺陷代码:在软件开发环节,开发人员因为水平、安全意识的诸多原因,往往会在开发过程中引入漏洞,这本身是一件十分正常的事情,但是对于开源软件而言,因为几乎是所有人都可以向开源项目提交代码,并且通过审核后就可以merge进项目,所以总会有不怀好意的人故意引入有问题的代码,比较典型的 case 是2021年4月,明尼苏达大学 Kangjie Lu 教授带领的研究团队因故意向 Linux 引入漏洞,导致整所大学被禁止参与 Linux 内核开发。除开道德问题,这种风险实际上有可能因为审核的疏忽导致风险直接被引入。
源代码平台被攻陷:其实 Git 平台本身由于保护不当,也有极大的概率被攻陷,虽然说攻陷GitHub这种平台本身不太现实,但是有很多开源项目都是自己搭设的Git平台,再加上一些众所周知的原因,Git平台本身缺乏保护是一件很大概率发生的事情,在2021年3月,PHP 的官方 Git 就遇到了类似的case,由于 PHP 官方 Git, PHP 团队在 git.php.net 服务器上维护的 php-src Git 仓库中被推送了两个恶意提交。攻击者在上游提交了一个神秘的改动,称其正在"修复排版",假装这是一个小的排版更正,并且伪造签名,让人以为这些提交是由已知的 PHP 开发者和维护者 Rasmus Lerdorf 和 Nikita Popov 完成的。所以Git平台的安全保护本身也是需要提高重视的。
代码branch被篡改导致打包结果不一致:由于开源项目的 Git 仓库是向所有人开放的,有些攻击者会尝试新建不同的 branch 植入代码然后进行发布,这样虽然编译过后的包带有CI/CD平台的签名,但是仍旧会引发严重的安全隐患,早在2019年的 DEFCON 会议上,就有安全研究员就发现了WebMin的1.890在默认配置中存在了一个很严重的高危漏洞,1.882 到 1.921 版本的 WebMin 会受到该漏洞影响。但奇怪的是,从 GitHub 上下载的版本却未受到影响,影响范围仅限于从SourceForge下载的特定版本的WebMin,后来经过调查后发现,是代码仓库没有添加分支保护机制出现了问题,引发此类安全风险。
CI/CD 体系被攻陷:在前面如果我们完成了代码完整性检测的话,如果流程没有被篡改或者构建平台运行正常,一般情况下出现问题的几率很低,但如果 CI/CD 平台和前面的 Git 一样被恶意篡改或是破坏,结果必定会出现安全隐患,SolarWind 事件就是由于这一原因导致的,攻击者在 CI/CD 过程中嵌入了后门,通过了签名校验,再通过 OTA 分发补丁之后导致出现了让人震惊的供应链攻击事件。
不安全组件引入:在依赖引入的过程中,如果引入了有问题的组件,则相当于引入了风险,这也是目前最典型的供应链攻击手段,通过我们对各个源的安全调查和分析后发现,投毒的重灾区在 Python 和 NodeJS 技术栈(一个原因是因为前端的挖矿已经很成熟,容易被黑产滥用,另外一个原因是Python的机器学习的库相当丰富,加上机器学习配套的计算环境性能强悍,导致挖矿的收益会比入侵普通IDC主机更高)。由于例子相当多,在这里就不一一列举了。
外部 CI/CD 流程构建:因为 CI/CD 平台有时候不能满足需求,或开发者出于其他因素考量,会使用非官方的 CI/CD 进行构建,而是自己上传打包好的 jar 或者 docker 镜像来部署,更有甚者会同时把打包工具链和源代码一起打包上传到容器实例,然后本地打包(极端情况下,有些“小可爱”的依赖仓库都是自己搭建的 Sonatype Nexus 源管理系统)。因为很多开源软件的使用者不会去做 CI/CD 的签名校验(比如说简单匹配下 hash),导致这类攻击时有发生。早在2008年的时候,亚利桑那大学的一个研究团队就对包括 APT、YUM 在内的 Linux 包管理平台进行了分析和研究,发现绝大多数源都不会对包进行校验,这些包随着分发,造成的安全问题也越来越广泛。
直接部署有问题的包:有些打包好的成品在使用的时候,因为没有做校验和检查,导致可能会部署一些有问题的包,最典型的例子是 Sonatype 之前披露的 Web-Broserify 包的事件,虽然这个包是使用了数百个合法软件开发的,但它会对收集目标系统的主机信息进行侦查,所以造成了相当大规模的影响。
过维护期的组件
在实际的生产环境中,有很多的开发者使用的运行时版本、组件版本以及 CI/CD 平台版本都是已经很久未更新的。虽然说站在安全的角度上讲,我们希望所有的系统都用上最新版本的组件和中间件,但是事实情况是,基于业务自身的规划迭代、大版本改动较多容易引发兼容性问题导致升级迁移成本过高等诸多原因,使得落地这件事情就变的不是那么容易。为了让安全性和易用性达到平衡,企业内部往往会妥协到通过其他手段收敛攻击面并且建立旁路的感知体系,保证除了安全问题可以及时发现和止损。但是长久看来引入过时版本的组件会引发诸多问题:
维保问题:因为开源社区的人力和精力有限,往往只能维护几个比较主要的版本(类似于操作系统中的 LTS 版本,即 Long-Term Support,长期支持版本是有社区的长期支持的,但是非 LTS 版本则没有),所以一旦使用过时很久的版本,在安全更新这一部分就会出现严重的断层现象,如果出现了高危漏洞,官方不维护,要么就是自己编写补丁修复,要么就是升级版本达到长痛不如短痛的效果,要么就是像一颗DSZD一样放在那里,祈求攻击者或者蓝军的运气差一点。
安全基线不完整:随着信息安全技术的发展和内生安全的推动,版本越新的安全组件往往会 secure by design,让研发安全的要求贯穿整个研发设计流程。但是早期由于技术、思路、攻击面的局限性,这一部分工作往往做了跟没做一样。感触特别深的两个例子一个是前几年 APT 组织利用的一个 Office 的 0day 漏洞瞄准的是 Office 中一个年久失修的组件,这个组件可能根本连基本的 GS(栈保护)、DEP(数据区不可执行)、ASLR(内存地址随机化)等现代的代码安全缓解机制都没有应用。熟悉虚拟化漏洞挖掘的同学们可能知道 QEMU/KVM 环境中比较大的一个攻击面是QEMU模拟出来的驱动程序,因为QEMU/KVM 模拟的驱动很多都是老旧版本,所以会存在很多现代化的安全缓解技术没有应用到这些驱动上面的情况,从而引入了攻击面。其实在开源软件的使用过程中也存在类似的情况,我们统称为使用不具备完整安全基线的开源软件。
未通过严谨的安全测试:现在的很多开源组件提供商诸如Sonatype会在分发前进行一定程度的安全检测,但是时间越早,检测的范围越小,换句话说就是,组件越老出现的问题越多。毕竟之前不像现在一样有好用的安全产品和安全思路,甚至开发的流程也没有嵌入安全要求。而这样就会导致很多时候新发布的版本在修复了一个漏洞的同时又引入了一个更大的漏洞,导致风险越来越大,越来越不可控。
综上,在安全团队的视角看来,风险无处不在。但是在一个非安全业务的安全公司,往往业务对于风险的理解和要求与安全团队可能大相迳庭。
业务视角下的安全研发风险
实际上在业务同学看来,他们也十分重视信息安全的相关工作,有些公司的业务技术团队甚至成立了专门的安全团队来协助研发同学处理安全相关的问题。可见业务不是排斥安全工作,而是缺乏合理化和可操作的安全指导,导致业务同学不知道我们有什么风险。在实际的组件风险修复过程中,我们也收到了很多业务同学的反馈和吐槽。总结起来有以下几种情况:
兼容性问题:在推动以版本升级为主要收敛手段的风险修复中,业务提出最多的质疑往往是兼容性问题,毕竟稳定性对于业务是非常重要的,所以一般情况下我们在推动升级的时候,往往会推送安全稳妥且稳定性最高的修复版本,作为主要的升级版本。但这种问题不是个例,每次遇到此类型推修的时候,业务都会问到类似问题。考虑到本文篇幅原因,这里就不展开讲具体的策略和方法。
安全版本的问题:和上一个问题类似,业务同学在引入组件的时候往往也会考虑安全性问题,但业务同学由于缺乏很多安全知识,导致自己对于“安全版本“的判断会有一定出入,所以业务同学会把这个问题抛给安全同学。但是安全团队也不能100%正确回答这个问题,因为开源组件这么多,我们不能像 Google、微软这种财大气粗的公司一样把市面上所有的组件安全性全都分析一遍,所以一般只能现用现查。这一来一去,会拉低这一部分的质量和效率。所以这一部分的需求也是重要且很急迫的。
追求“绝对安全”:有些业务同学会直接问你,我到底该怎么干,我才能安全地用各种组件?话虽直接,但是能够体现出背后的问题——安全的尺度和评价标准不够透明。提升安全的可量化并且追求标准透明也是非常急迫的,考虑到这是一个运营的问题,在此就不展开叙述了。
合规问题:很多业务会不了解开源协议导致不小心违反了开源协议的约束,引发法务问题。
从实际情况来看,业务同学并不是不想做安全,很多时候是缺乏一个有效的机制,告诉他们引入的软件依赖是否安全,需要完成那些操作和配置才能让开源组件用着安全。作为安全工程师而言,我们需要站在业务的立场上去设身处地想想,这些问题是不是真的不能被解决。由于业务和安全双方都有关于组件安全相关的需求,恰好 SCA 这项技术可以很好地满足业务和自身的需求,所以在整个 SCA 建设的过程中,我们需要不断去挖掘这些需求。
SCA 建设的过程
SCA 其实并不是一项很先进的技术,只是在现代的研发过程中随着流程的标准化、组件的丰富化、开源社区的活跃以及开发成本的降低等诸多原因,使得一个项目中纯自己写的代码占整个项目中全部代码的比例越来越低了。也就意味着供应链的问题产生的影响会越来越大,随着 DevSecOps 的火爆,重新带火了 SCA 这一传统的技术。
根据很多企业内部的实践以及业界对于 SCA 技术的理解,我们认为 SCA 比较核心的功能有以下几点:
软件资产的透视:企业内部需要对所有的应用系统引用了哪些组件这件事情有着非常清晰的认知,在考虑尽量多的情况下覆盖绝大多数的场景(业务应用系统、Hadoop 作业等数据服务、Puppet 等运维服务等),并且研究他们的开发流程,分析哪些阶段可以引入 SCA 能力做风险发现。
风险数据的发现:现在是一个数据爆炸的时代,安全团队每天需要关注的安全风险信息来源五花八门,但是需要尽可能多地去收集风险相关的数据,并且做上下文整合,使之可以自动化和半自动化地运营起来。但仔细想一下,除了追求风险数量,能否更进一步追求更强的实效性,达到先发制人的效果?通过企业内部多年的安全威胁情报能力建设,同时追求实效性和可用性的双重SLA是可行的。除此之外,需要关注的风险不能仅仅局限于漏洞和投毒这两个场景,还需要对开源软件的基线信息也进行收集。
风险与资产关联基础设施的建设:以上的两个方向是在数据维度的需求,考虑 SCA 落地不单单是信息安全部门的事情,实际落地过程中需要与业务自己的质量效率团队、运维团队建立良性的互动机制,让安全能力深入到业务,所以需要建设相关的基础设施去实现核心API能力的建设,对业务赋能。虽然听上去很简单,但实际上开发的东西可能是 UDF 函数,也可能是某些分析服务的插件,甚至可能是CEP(Complex Event Process复杂事件处理,一种应用于实时计算的分析技术)的规则。
可视化相关需求:既然有了风险,安全团队及业务相关团队的同学除了自己知道之外,还需要让负责系统开发相关同学也知道风险的存在,并且要及时给出解决方案,指导业务完成修复,同时安全团队也需要通过获取运营数据知道风险的修复进度。
正所谓罗马不是一日建成的,虽然现在确定了 SCA 建设需求和建设的方向,但是落地起来的话仍然需要分阶段完成。正如建设其他的安全子系统一样,安全团队需要按照从基础数据/SOP 建设到平台化系统化的建设来完成整个 SCA 能力的落地。所以在实际操作过程中,应该将整体建设分成三个阶段进行:
第一阶段:数据盘点与收集,在项目建设前期,信息安全团队应当和企业内部的基础架构相关的团队,完成企业内部基础组件的数据资产盘点,旨在从基础技术和信息安全的视角实现对研发技术栈、研发流程链路的摸排,在合适的位置进行数据卡点获取相关数据,完成对资产数据的采集。另一方面,信息安全部门在现有的威胁情报经验和数据上,对组件数据进行数据封装和整合,建立一个单独的开源组件风险数据库,旨在收集来自于全量互联网上披露的风险,方便与后面的资产数据进行联动。
第二阶段:SOP(Standard Operating Procedure,标准运营流程)和概念验证建设,信息安全团队通过自己的漏洞修复经验进行SOP的固化,通过不断地调优,完成一个通用的漏洞修复 SOP,通过实际的演练和概念验证(PoC,即Proof-of-Concept)证明该 SOP 可以在现有的技术条件下很好地完成风险修复这一部分工作。同时结合 SOP,对之前收集的资产数据和风险数据进行查漏补缺,完成对数据和数据链路的校验工作,保证系统高可用。在这个阶段,SCA 的服务提供方需要开放部分的核心API给部分业务的质量效率团队,帮助进行测试并收集使用反馈,让其融入自己的风险治理环节。
第三阶段:平台化及配套稳定工作的建设:当 SOP 初步成型并且完成了概念验证之后,应当需要建设对应的平台和子系统,让这一部分工作脱离手动统计,使其接近 100% 线上化。得益于内部 SOC 的模块化设计,可以在现有的平台上轻松构建出 SCA 相关的子系统,完成能力的数据。针对终端用户可视化风险这一问题,SCA 子系统会提供核心的 APIs 给面向研发同学端的 SOC 完成风险信息的同步。为了保证服务的高可用,后续还会建设配套的数据链路检查机制,不断完善数据可用性。
一些比较重要的工作如上图所示。三个阶段完成之后,SCA 的能力大概就建设好了,但在建设过程中,安全团队需要考虑很多东西。笔者个人认为如果说安全厂商的安全产品和服务可以被认为是问题解决的分子的话,甲方安全团队的工作更多的是做大做全分母,要把各种情况都考虑面面俱到,才能保证风险不被遗漏。
首先来说在资产建设方面,企业内部的安全团队、质量效率团队以及数据平台团队等存在研发流程的技术团队,需要配合完成自己所辖的 CI/CD 系统数据和数据服务构建数据的采集工作,同时也在为IDE插件团队提供了 SCA 的 API,完成了从代码开发环节到应用上线环节的数据采集。但是我们在应用这一部分数据之后发现了很多问题,除开数据本身质量和准确度不谈(不谈不代表重要,相反这一部分很重要,后面会介绍这一部分),按照前面提到的场景,还会有很多额外场景,比如说业务在灰度了一部分之后就忘掉了还没灰度完,导致一个服务下面只修复了一部分机器,再比如有很多的“小可爱”会绕过企业本身的 CI/CD 流程进行部署操作(有些甚至还是自己人)。为了考虑到这些额外的情况,我们应该从主机的粒度重新考虑这件事情,也就是说通过主机实例(docker容器、虚拟机、物理机)本地的 HIDS agent ,完成文件信息、进程信息、环境变量、shell-log 等信息的分析,确定主机实例修复完毕了。这样我们就建立了一个构建链路-主机维度的数据正反校验机制,理论上讲主机端 HIDS agent 覆盖度和存活率都达标的话,我们几乎可以得到一份详细的软件资产的数据(当然数据不准、延迟这些问题是肯定还会有的),详细的落地核心工程和结构关系看下图:
在数据确定覆盖的差不多的时候,我们需要通过数据总线传递给数据仓库和计算引擎,完成数据的交叉和分析工作,得出的结果便是存在哪些风险和风险进度。在这里实时引擎一方面需要承担增量资产数据的分析,另一方面也会保存很多聚合的 CEP 规则进行分析。离线引擎则是完成存量风险的周期性发现和治理工作。
讨论完资产数据的采集之后,我们来谈论风险数据的收集。早在威胁情报体系化建设阶段,组件漏洞情报就作为基础安全情报应用场景下漏洞情报的一个子集一直存在,但由于之前局限于“漏洞=风险”的观念,导致实际执行过程中只存放了组件漏洞相关的风险信息,在综合评估完现有的需求和实际情况之后,发现当前组件漏洞数据,只能承担一部分研发安全风险的治理工作,而像对于供应链投毒、开源组件基线情况等其他类型的风险数据,由于当时还没有数据能够提供成熟的能力输出给业务方使用,经历过充分的讨论和调研之后,决定将组件相关的漏洞数据独立出来,并且新增采集供应链安全的其他风险数据,重新建立一个组件安全相关的数据库,完成风险数据的存储和应用。通过结合自身威胁情报的实践和业界关于组件风险收集的最佳实践来看,打算从5个维度实现对组件相关的风险进行收集和存储:
NVD/CNVD/GitHub-GHSA 等通用漏洞数据库:这个是基本操作,旨在收集漏洞风险,结合漏洞实际情况进行人工和研判。
开源组件提供商的 Jira、Commit、Release 和 Bugzilia 等 Pull-Request 相关的数据:通过获取相关的数据,结合自研的 NLP(Natural Language Process,自然语言分析)分析引擎对内容进行倾向性判断,过滤并输出安全相关的信息,然后组织人工或自动化研判,通过实践发现可以大幅度提前发现风险(笔者在 ISC2019 上曾经阐述过风险发现前置的必要性和落地经验)。
组件专用风险库:经过我们对于漏洞数据相关的调研,诸如 Github 和 Snyk 这些机构会有专门的组件风险库对外提供,通过获取并分析这些信息,经过加工后可以得到可用性极高的组件风险库,可按需研判。
软件风险相关的新闻资讯和 RSS 订阅:这类源主要是解决 0day 和被 APT 组织在野利用等特殊披露的漏洞,同 Pull-Request 数据一样,该类型的绝大部分风险数据都是需要通过NLP分析引擎进行情报数据分析,进一步进行情感推断后才达到可用标准。
手动录入:也是常规操作,虽然采集了很多类型的风险,但的确受限于供应链攻击的多种多样和发展,所以不可能考虑的面面俱到,所以仍旧需要手动接口补充需要运营的风险。但安全团队仍希望将手动录入的风险占全部风险的比例,控制到一个合理的范围,保证这部分能力不会因为运营人员的问题(如经验不足、离职等)而导致能力的闪崩性缺失。
通过上面的信息,我们发现这里面绝大部分数据都是非结构化的,换句话说就是不可以直接拿来使用,需要处理(异构数据、自然语言数据)后才可以使用,所以我们在处理时会引入 NLP 分析引擎并且对漏洞风险数据打标后(主要工作是添加 RepoID 用来和资产数据联动),才可以向下传递给数据引擎和 APIs 。(从威胁情报数据建设的角度来看,2019 年前后,基础安全相关的威胁情报实现了结构情报和非结构情报约为 1:1 ,现在非结构的情报数据远高于结构化的情报数据,这也越来越接近于设计的目标),具体的落地核心工作内容和关系结构如下图所示:
在风险信息处置环节,实时计算引擎和离线引擎的作用与资产数据处理的时候是一致的,主要解决增量和存量的问题。同时考虑到业务自身会有自助排查风险的需求,SCA 平台也会提供一些核心的 APIs 给业务方。
在开始着手建设这些数据相关的基础设施时,需要提出一些建设指标,防止一些关键的功能因为平台本身的问题,导致服务大规模不可用。在资产方面,目前资产数据库的基础设施可以支持 TB 级别资产数据的检索能力,返回时间不超过 100 毫秒;而在风险数据建设方面,目前覆盖了共计 10 个技术栈(包含主流的 Maven/Gradle、PyPi、NPM、SPM、APT/Yum、CocoaPods 在内)共计约 59 万条风险数据,更新周期在两小时以内,通过计算引擎可以和资产数据进行快速匹配,节省了将近 95% 的受影响资产排查时间,大大提升了运营效率。
在匹配规则建设方面,因为数据来源较多且杂乱,通过自研的NLP分析引擎进行大规模的训练和处理数据之后,可以统一到一个比较固定的数据结构里面,在打标处理后可以实现和资产数据的高效联动。鉴于 NLP 模型的训练过程和训练方法不属于 SCA 建设过程中比较重要的技术,所以本文中不会展开叙述详细的训练过程和情感推断训练过程。除了资产信息关联之外,风险数据库可以同时实现对 CVSS(即 Common Vulnerability Scoring System,即通用脆弱性评分系统)的匹配,及时推送满足 CVSS 影响范围(这里不是指 CVSS 分数,而是指 CVSS 的描述表达式)的漏洞信息,提醒安全运营的同学关注相关风险并及时进行研判。
对于风险的基线数据,目前基线建设数据没有一个相对完整的参考标准,但是 Google 推动成立的 OpenSSF基金会(Open Source Security Foundation,在 Google 等互联网企业和美国政府的推动下成立的开源组件安全基金会)在 2021 年下旬发布的 ScoreCard 功能是一个很好的参考标准,结合同样是 OpenSSF 推出的 AllStar 基线检测工具,可以完美补充组件基线相关的数据。
SCA 建设中遇到的问题
在 SCA 建设过程中,实际上并不是一帆风顺的,总结一下困难的地方,有以下几个方面:
漏洞-资产关联规则缺乏一个成熟且有效的行业标准:在 SCA 领域,目前没有一个成熟的可以匹敌 NVD 相关的生态环境,在 NVD 体系下,有用来描述漏洞信息的 CVE ,有描述资产影响范围的 CPE(Common Product Enumunation),有描述攻击路径的 CAPEC(Common Attack Pattern Enumeration and Classification),还有描述风险类型的 CWE(Common Weakness Enumunation),但是在组件安全领域,由于各家公司的基础设施建设成熟度和技术选型差异巨大,所以没有一个可用的完整生态可以做到开箱即用,所以我们需要基于现有的技术架构和基础设施来设计自己的规则,同时推广这套标准在安全运营工作中落地。
数据质量与数据链路的可靠性:数据质量和可用问题是自打立项开始一直到后期运营都会出现的问题,问题可能来自于上游采集逻辑不完备或采集错了的原因,还有数据链路不稳定导致写入计算引擎出现大批量丢失的问题,还有数据链路没有检查机制导致不知道具体问题出在哪里,甚至由于使用的数据分析技术栈的原因,导致打过来的数据是错乱的,错乱的数据有可能会影响CEP规则的准确性和有效性。这当中的有些问题不是偶发的,甚至有些问题是在真实应用的场景下仍旧会高频出现,所以建立一个长效的数据拨测机制和数据污点追踪能力是必要且必须的。
风险数据的数据结构与准确度:由于在风险数据中引入了过多的来源,且大量引入了机器学习和NLP技术把非结构化数据转换成结构化数据,考虑到模型训练的精度、训练样本数据、训练网络等问题,导致平台提取出来的漏洞信息很多时候会有一定的出入,并且由于风险情报数据比较依赖上下文和实效性,所以需要在各方面做取舍,这个问题其实和数据的问题一样,不是一朝一夕能解决的,需要大量的实践运营和拨测机制case by case地去推动解决。
CI/CD管制与非标准资产的治理:这一方面实际上与 SCA 落地的关系不是很大,但是拿出来的原因是 SCA 本身是一个需要强关联研发流程的能力,好的 SCA 平台除了可以提供标准化的APIs和GUI让用户快捷操作,同时也需要兼容非标准的发布流程和上线标准,这就是为什么除了主要的几个技术栈之外仍旧覆盖了一些偏小众的技术栈,如C#/Powershell的NuGet、ErLang的Hex包管管理等。
资产透视深度:这一部分其实是 SCA 核心能力的体现,从理论上讲,SCA 是有能力分析诸如FatJar这种开源组件嵌套的jar包,但实际上受制于数据质量和技术能力,往往无法分析到一个非常细的粒度,所以这一部分需要去设计一个MTI(maximum tolerate index在这里表示可接受的最粗分析粒度)指标去指导相关的设计。
SCA 技术未来的展望
在建设过程中,我们参考了很多公司和商业产品对于组件风险分析和治理的最佳实践,翻阅了大量与软件成分分析技术以及软件供应链安全治理相关的论文文献、公开的专利以及企业的博客。其中 OpenSSF 基金会的一些研究成果让人印象深刻。在2021年6月份 OpenSSF 发布 SLSA (Supply chain Levels for Software Artifacts,即软件供应链安全等级)之后,围绕 SLSA 这一套标准陆续发布了很多有助于我们分析的数据服务和产品,比如准 SCA 产品 Open Source Insight,漏洞风险库 OSV(Open Source Vulnerabilities,开源组件风险数据),软件安全基线检查工具 AllStar 和 ScoreCard,开源组件风险奖励计划 SOS Rewards(可以理解为是开源组件的漏洞奖励计划)。可以初步看到未来 SCA 的建设路线一定是三个方向:追求足够细粒度的资产和风险透视能力,风险的主动识别能力和开源软件的基线检查能力。换句话说,SCA如果想做到足够有效,需要覆盖从软件开发到上线的所有环节,包括代码完整性、流程完整性和基线巡检功能,都会需要 SCA 的核心能力。
除了 SCA 提供的风险透视能力,在整个DevSecOps环节,安全团队、质量效率团队、运维团队和业务团队需要非常默契的配合,大家各司其职共同解决研发方面的风险,在这其中,安全团队能够提供的,除了风险数据和修复建议之外,还需要提供一些对应的基础设施帮助业务团队更高效地处置风险。扩展到整个开源软件风险治理方面,也可以给大家一个 cheatsheet 做参考。
当然想要做到以上所有的项目,实际上对于企业的基础架构和基础设施有一定的要求,但好在目前开源社区对于供应链安全治理提供了一些安全的解决方案,诸如国外由 OpenSSF 或者商业公司牵头设计开发的一系列工具链,如 ChainGuard.dev,SigStore,Anchore 等,当然国内也有很多优秀的开源解决方案。可以在进行一定修改之后,集成到现有的基础架构中。
考虑到安全的对抗属性在里面,SCA 工具如果融合进企业内的研发流程中,必然会引发很多对抗 SCA 检测的路子,况且在调研过程和实际处置过程中,绕过固有研发流程的情况是比较常见的,所以后续在继续建设 SCA 能力的过程中会逐步加入对抗的检测和加固,防止漏网之鱼。
结语
以上为在整个 SCA 能力建设过程中的一些想法和实践,在建设 SCA 能力的过程中,通过与各团队的协同工作和沟通,了解了很多业务对于组件安全方面的想法和真实需求,通过需求得出需要建设的能力,在技术方案落地中,企业内部部署的很多安全产品,诸如HIDS Agent和RASP等,可以从主机的角度去反向验证建设的过程是否正确。SCA 能力的落地离不开安全团队与业务团队的配合。实际上在 SCA 的建设过程中,我们如果再往更深层次去看,会发现诸如闭源软件、开源软件的跨架构、跨编译器的识别、其他载体(比如容器镜像、软件成品)的安全分析等,这些技术挑战对于实际企业内落地 SCA 能力而言还是蛮高的,考虑到目前的解决方案还停留在 PoC 阶段,故不在本文中提及。
如果抛开整个落地的过程,考虑到各家在基础设施、核心技术栈、主机信息监控能力的参差不齐,所以必定会有不能落地的地方。而站在安全服务提供商的角度上看,SCA 相关的产品未来建设的过程中可能需要更加轻量化和开放协同化。所谓轻量化,是指产品的核心功能可以在脱离基础设施多种多样的前提下,能够稳定高效的去提供核心能力,做到很好地与客户的研发流程完美衔接,从调研结果来看,目前市面上所有的 SCA 产品,基本上都存在一个架构设计比较重的问题,不能很好去融入现有的CI/CD流程。所谓开放协同化是指,可以通过多种方式去和其他的安全产品和安全能力提供数据的共享机制,实现与其他安全设备在数据上的联动,互相补齐对应的风险发现能力,做到简洁和高效。
以上是我们对 SCA 能力建设过程当中的想法。