IT主管必看:软件供应链安全风险指北

409 阅读20分钟

作为企业主管,你是否知道你的工程师随便编写的一个返回"Hello World"这么简单的微服务,后面居然依赖着上百个软件包、5 万多行代码?你又是否知道这些软件包在开源世界的来源、它们能带来什么样的安全风暴?

“Hello,World”后面可能有几万行代码

每一个软件工程师在学习一门新技术的时候,都会从最简单的“Hello,World”程序开始。可是世界上确实没有免费午餐 - 表面越简单的东西背后的代价可能也越大。例如,你想用JavaScript+Node.js开发一个只能对网络请求返回“Hello,World”回复的微服务,你决定采用一个最轻量简约的微服务框架ExpressJS - 一动手的瞬间,你的开发工具npm就给你从上游拉取100+软件包 - 54,000行代码拿去,不谢。如果你想再玩点高级功能,例如添加一个MVC框架(例如Locomotive),你的这个“微”服务实际代码量马上升至220,000行 - 不好意思,起步价,哪怕你只写一行代码。

上述情况不限于JavaScript/Node.js,对其他语言环境也一样。现在的计算机语言,Java、Golang、Rust、Ruby、Python、Julia... 不可胜数,都自带包管理工具、“零部件”中央仓库、以及庞大的开发生态。

learn-packages-by-ecosystem

上图为每年各语言新增软件包数量,其中npm生态2019年新增超过30万个。上图缺乏新兴语言如Golang、Rust等的数据,但这些语言生态中的“零配件”数量的快速增长,对于开发工程师来说,都是可直接感知的。相比之下,Java、Ruby的组件生态增长率较低,但很大程度因为它们已经增长了近二十年,基数已经极其庞大。

根源:全球化的开源大生产

开源软件运动如火如荼的进行了二十四五年(如果从1998年2月3日在硅谷的一次会议中首次提出“open source”一说开始算 - 当时互联网先驱Netscape刚刚宣布开放他们的浏览器源码),极大程度的改变了软件业的面貌。当前全球企业超过90%直接或者间接甚至在无意识中使用了开源技术。

可以说,今天我们开发的几乎每一套软件,都是全球化生产协作的结果。例如无数Java工程项目几乎必然依赖的基本日志工具Log4J,最早在二十一年前由瑞士程序员Ceki Gülcü个人独立开发提供;多少互联网公司牛哄哄声称自主研发的浏览器,内核来自谷歌的Chromium;再有技术能耐的银行证券金融巨头的网站和用户端,也离不开React、Vue、Electron、Qt等前端基础框架;马斯克的SpaceX火箭和Tesla汽车,操作系统和软件工具也离不开Linux和GCC编译器。

计算机领域有一句格言,“"All problems in computer science can be solved by another level of indirection",被称之为“软件工程基本定理”("fundamental theorem of software engineering"),分层(layering)- 这就是计算机领域解决问题的一个典型的、最根本的思维方法。这很好的解释了软件供应链的需要 - 从硬件、网络层、操作系统、虚拟化管理软件、中间件、开发工具、开发框架、前端组件、辅助代码库,到编译器、解析器、运行时,层层叠叠,每一层面对自己的领域、解决好自己的问题,最终到达面向终极用户的应用软件,再大的公司、再牛的工程师,都难以自己包打天下。全球化和开源运动相辅相成,而软件技术人则在这个开源世界的“乌托邦”相互成就。

但问题也就来了:在你的供应链上的各种“零部件”,不仅面临“依赖地狱”的挑战,你甚至还无法知道这些零部件的依赖传递关系、不了解它们的作者和来源。

虚拟世界的供应链远比物理世界的无序凌乱

一套软件的供应链,如果把它画出来,很有可能是这样的:

dependency-graph

产品P,依赖于子系统/组件/基础库A、B、C、D、E,其中A又依赖于F、G、H...,B则依赖于G、H、X、Y、Z,而G又可能依赖于H... 有些情况下,还可能出现循环依赖 - A依赖于B,B依赖于C,而C依赖于A... 这就是传说中的dependency hell(“依赖地狱”)。

可是这还只是复杂性的一个维度!每一个软件零部件还有不断变化中的版本:产品P版本1.2必须依赖于零部件A的版本2.5.1、而该版本又必须建立在零部件B的版本1.0.3基础上...

某些物理世界的产业链中,产品和零配件也可以类比“版本”一说,例如2022年版的某型号汽车,可能采用2021年版的某汽配件X,但该型号汽车的2021年版则可能采用X略有规格变化的更早期版本... 但是,物理世界的零配件,不可能像虚拟世界的零配件那么频繁的发布版本 - 由主版本、此版本、修订号等繁复的组合而成(见“语义化规范”;而且也不可能像软件组件那样存在“循环依赖”的风险。

可以说,今天的绝大部分开发者,根本搞不清楚自己的软件供应链里都有谁,因为他们所用到的很多技术组件都是他人提供的,这些“上游”组件本身又用了什么其他组件、工具,开发者们往往不知道也不关注。可以说,我们在生产一个软件产品的时候,很可能“非自愿”的集成了大量“上游”、“上游的上游”、“上游的上游”的半成品。

相比之下,物理世界的产业链没有这种不可控的问题存在 - 特斯拉、比亚迪的每一辆车,用到的每一个零配件的生产商都是100%确定的。

软件供应链的四大风险

企业的基层开发人员,往往并不关注(也难以有能力和工具去评估)自己的代码所间接、被动引用的第三方代码包的来源、质量、安全风险。传统企业的IT主管、CIO们,焦点在业务科技赋能、企业科技战略布局等宏观事情上,或者在生产环境质量保障、紧急情况的灭火上,越是高级管理层,越有可能已经远离一线的战阵,十年以上技术管理资历的管理层,很可能在充当码农手写代码的当年,像npm、cargo、gradle之类今天无处不在的“软件零部件”管理工具(package manager)还没有成型或出现,对一个“Hello,World”微服务后面可能隐藏着几万行代码这种情况,未必有亲身体验,对其中的风险了解不足,基层工程师采用一个开源包只是一行命令一个回车的举手之劳,足以让坐在IT金字塔顶层的CIO们坐在火坑上而不自知。

对于企业来说,当前软件供应链起码面临四类风险。

  • 软件质量风险。
  • 长期支持风险
  • 知识产权风险。
  • 信息安全风险。

在信息化程度比较高的金融业,软件作为金融信息基础设施的重要组成部分,安全问题将直接影响金融信息系统的安全稳定运行。

对于企业们来说,你的所谓“信息安全”、“安全加固”,也就取决于xkcd.com画的这张图右下角那块小积木 - 可能是地球上随便哪个地方的一个路人甲工程师以无私“活雷锋”精神默默耕耘多年奉献的一段代码:

dependency_2x-3

Supply Chain Attack - 软件供应链攻击

在复杂混乱的软件供应链之下,黑客利用其中的漏洞进行安全攻击,从中渔利,是显而易见的。当程序员在开发软件的过程中无知觉的使用了被恶意篡改的零部件,所开发出来的系统可以说天生就埋入了危险种子。以前段时间闹的非常严重的Log4J远程代码执行漏洞问题为例,一个存在了近二十年、极其大量的为开发者采用从而在无数的互联网网站、企业软件、Web工具中运行的日志记录组件,让使用它的工程师做梦也想不到。这类攻击,隐蔽性极高 - 你的代码不用Log4J不等于你所依赖使用的第三方代码或者它们所依赖的上游代码不用。

正因为其隐蔽性,大大增加黑客的兴趣,这一类攻击正在迅速增长,以至于拜登政府都不得不视之为严重危害。随之而来是科技企业共同推动下,拜登政府成立开源安全相关的基金,以长期资助促进对安全漏洞的监控和修复。

Screenshot-2022-06-22-at-9.58.18-PM

根据Gartner的报告,到2025年全球将有45%的机构组织遭遇所谓的软件供应链攻击 - 是2021年的3倍。这些攻击一旦成功,对于黑客而言经济利益巨大,对被攻击的企业则是摧毁性的 - 不仅危害运行遭受攻击的企业,更可能因为其商业数据、用户数据的丢失而延伸至损害受损企业的客户。数字化世界里,安全攻击往往是有网络效应的、传染性的。

软件世界虚拟供应链攻击的严重性隐蔽性,如果和物理世界类比,还是拿汽车产业做比喻:车厂所造的汽车里不知不觉用到的某些零部件,不仅有质量风险,甚至还可能反过来搞破坏,例如监控驾驶者的行车数据偷窃发送给黑客。如果把汽车换成火车甚至军舰,可以想象所带来的灾难。

总之,“恶意”这俩字,不仅在现实世界,在软件世界也是满满的。怎样把“恶意”关在笼子里?

安全运行沙箱类技术的崛起

虚拟世界的“恶意”代码,也只能用虚拟的“牢笼”去“关住”它。安全沙箱(Security Sandbox),就是这么一种数字牢笼,它的形态和技术实现方式有很多种,本质上它是一种安全隔离机制,通过构建一个封闭的软件环境,隔离了它所在的“宿主”的资源包括内存、文件系统、网络等等的访问权限。运行在这个封闭环境中的进程,其代码不受信任,进程不能因为其自身的稳定性导致沙箱的崩溃从而影响宿主系统,进程也无法突破沙箱的安全管控以读写宿主系统的资源。

沙箱类技术以各种形态出现:在BSD等操作系统里就提供直接叫做“Jail”的虚拟化隔离;在JVM里为了支持Java Applet这里网络加载的代码的运行,实现了sandbox机制;浏览器里的HTML渲染引擎,一定程度上也可以视为一种在用户态的基于安全能力模型(Capability-based)的沙箱技术。

在云计算的环境下,云原生型安全沙箱技术也在演进,有望在企业环境中,对软件供应链安全问题提供一部分“治标”的解决方案(“治本”还得更加长期、综合、涉及面更广的综合策略)。

FinClip:前端安全沙箱技术

FinClip是一种新型的轻应用技术,它有一个比较有趣的逻辑:企业的软件供应链在数字化时代可能是需要被重新定义的 - 有可能你的合作伙伴的代码运行在你这里、也有可能你的代码借道合作伙伴的平台去触达对方的客户。FinClip的核心是一个可嵌入任何iOS/Android App、Windows/MacOS/Linux Desktop Software、Android/Linux操作系统、IoT/车载系统的多终端安全运行沙箱。

FinClip安全沙箱中运行的轻应用,选择了兼容互联网主流的小程序规范。这是一个非常明智的设计,FinClip的开发团队没有重新发明自己的技术规格,而是全力支持小程序这种形态的轻应用,一方面是因为小程序类技术的体验和效果在互联网上得到充分验证、获得巨大成功,另一方面是网上积累了丰富的技术生态、开发框架、以及更重要的 - 人才资源,从而让企业IT几乎是无缝掌握这个技术,能迅速投入应用。

Screenshot-2022-06-24-at-9.48.50-PM

FinClip的嵌入式安全沙箱,又被称之为小程序容器,它的本质其实是建立在Security Capability model基础上的浏览器内核的扩展,其沙箱的特点,体现在三个方面:

  • 沙箱内小程序之间的隔离
  • 沙箱对运行其中的小程序代码,隔离其对宿主环境的资源访问。以一家银行与它的合作生态为例,银行在自己的App上引入了衣食住行各类消费场景的小程序,这些小程序均非本行开发,也不能访问到当前宿主App的任何数据资源
  • 沙箱隔离了宿主对于沙箱中运行的小程序所产生的数据。以一家银行与一家券商的合作为例,券商把自己的业务小程序投放到银行的App中,银行App作为宿主,并不能访问沙箱内部该小程序的运行数据(当然,这是需要有一定的行业规范、监管政策去约束,但技术上首先是完全可能)

换句话说,FinClip试图构建一个Zero Trust(“零信任”)环境,不管小程序的“供应商”是谁,它们的代码都被隔离、同时也被保护在沙箱环境中。

FinClip安全沙箱还配备了云端的管控后台,让任何小程序可以被关联到指定的App宿主所嵌的沙箱实例中,从而能且仅能运行在某一款App或者某一个终端上。像互联网小程序一样,FinClip的小程序也可以被实时上下架,对于金融机构来说,起到“实时风控”的效果,因为上下架的管理工具和权限,都由企业私有化运行、自行负责。任何有潜在安全风险的前端代码,一经发现即可瞬间下架,用户端再也无法打开使用。

这些安全管控的能力,可以说是企业尤其是金融机构数字化转型所必须。对于企业而言,内部IT、外部合作伙伴,均可以作为“供应商”以小程序方式实现、提供数字化场景,从而形成数字生态。

Deno:云端安全沙箱技术

Deno是Node.js的发明者Ryan Dahl的重新发明。在推动服务器端JavaScript的应用生态获得巨大成功后,Ryan也看到Node.js的很多存在问题,在2018年的一次公开演讲中,提到了其为Node.js感到后悔的十件事。最终他另起炉灶,按自己的理想重新打造一个新的技术,也就是Deno,其中最重要的设计考虑就是安全优先、为deno技术设计的第一性、并采用V8引擎作为JavaScript运行的安全沙箱。

deno-sandbox
[缺省运行在Deno的沙箱里的代码,没有对沙箱以外任何资源的访问权]

当然,Deno不仅是一个安全沙箱,在本文我们仅从这个角度去谈论它。它的野心不仅在于替代Node.js把之前没有做对的事情做对,它基于Rust语言实现,支持WebAssembly,提出了“Isolated Cloud”(隔离云)的概念,给互联网提供比docker等容器类技术更加轻量和启动时间更短、实现进程级隔离的新一代安全基础技术设施,最新消息是几天前由红杉资本领投获得了新一轮2100万美元的投资。

治本的综合防范策略

安全沙箱技术的采用,不失为一个短期见效的治标方案,相信早晚会成为企业数字技术安全的标配。但是长远的治本,需要更加综合的策略,起码有以下几点。

Shift-left:“左移”安全焦点

什么是“左移”(shift-left)?

我们IT所绘制的SDLC(Software Development Lifecycle) - 软件开发生命周期阶段图中,一般习惯于把开发阶段画在最左边,然后依次向右是测试(功能性与非功能性)、部署、运维。一直以来,IT习惯于在非功能性测试阶段就性能、高可用、健壮性、安全等进行检测,到最后再来一道“安全加固”,然后上线。所谓安全策略,基本上是运维阶段的事后补票。

Shift-left的宗旨,就是我们要把安全焦点左移至开发阶段,对开发阶段所依赖的软件供应链进行检测,搞清楚自己的软件的(1)where - 是在哪里开发的、源头为何,(2)how - 怎样开发的、“工艺流程”为何。

事实上每次发生Log4J这类安全漏洞,最终出来负责修复(和背锅)的还是开发人员,不是运维人员。软件供应链上的风险,只能左移至开发阶段防控。

这几年越来越多的IT在建立DevOps实践,但是,现在恐怕应该一步到位迈向DevSecOps。

SBOM:掌握自己的软件“物料清单”

首先是建立高度自动化、智能化的CI/CD流水线,让安全检测和功能测试、回归测试接受同等待遇,充分利用安全检测工具去分析软件生产过程中不同阶段的潜在漏洞和风险。在这里,要坚持的宗旨不是“完美无缺”的安全检测,而是“从小处做起”,形成“反复验证”、“持续优化”、“迭代”的循环。

近年来针对软件供应链安全出现的工具门类SCA(Software Composition Analysis),值得关注和运用。这类工具,顾名思义,就是对复杂的软件包的组成、依赖关系、传递依赖关系进行分析,向企业提供潜在安全风险的预警。通常SCA类工具,能检测包管理工具(package manager)、启动清单文件(manifest file)、源代码(source code)、二进制文件(binary)、容器镜像(container image)、软件许可证(License & Permit)等等,最终为企业生成完整呈现传递依赖关系的“物料清单”(Software Bill of Materials - 简称SBOM),并以之与网上某些政府或者可信商业组织运行维护的安全风险数据库进行比对,从而就企业客户当前的软件的安全风险、知识产权风险作出评估反馈。

每一家企业,只要用到开源的“零配件”,最终可能都需要一张自己的SBOM。

Database:从外部获得公共安全设施的支持

光有SBOM还不行,需要公共的安全攻击事件库、开源软件漏洞数据库,统一收集全球性的相关的数据,一方面调动公众参与提供最及时的信息,另一方面提供协议、接口,以支持自动化的安全漏洞管理工具。这方面美国国家标准技术研究所(NIST - National Institute of Standards and Technology)提供了示范,他们运行一个称之为NVD(National Vulnerability Database)的公共数据库,并通过SCAP(Security Content Automation Protocol)协议规范了这些安全漏洞数据相关的命名、格式,让工具开发商在安全漏洞检测、评估和自动化处理的应用工具中连接、更新和使用数据。例如一家使用这种工具的企业,不仅获得一张SBOM,还可以实时基于NVD数据库进行校验,从而及时评估自己的风险。

今天的开源代码在软件世界可以称得上“无远弗届”,安全漏洞的发现与弥补,也不是单一企业能解决,需要权威可信的公共设施的支持配合。

这好比食品行业的供应链,你一家小餐厅能保证所采购的猪肉不是死猪肉、进货的调味料没有地下作坊掺和的有毒化学品?食品行业有卫生组织的监督、黑名单、法律追责。在跨国的虚拟世界,需要全球的公共资源配合,共同维护个黑名单、共享预警,已经是必要条件。

Governance:在内部建立软件开发的安全治理

大概在十五年前,国际的大型银行、华尔街的巨头们,大部分都建立了一定的内部开源技术白名单,相比之下,国内金融机构们的IT是否已经完善类似的制度,没有公开的统计数字可考,但要打个问号。

另一方面,开源技术白名单,在这些传统国际金融巨头里,其实也有相当大的弊病。例如某美国银行,直至2017年,白名单上可用的开源软件依然是“远古”版本的Apache、Tomcat,导致软件厂商、开发商为了符合该银行的要求而不得不“降级”自己的零部件。过于保守的白名单策略,阻碍了企业的技术发展,甚至制造额外不必要的成本。而且古老稳定的开源软件版本,并不等同于安全,安全漏洞这种东西可真是不分时段,任何软件的设计与运行,总是基于一定的环境假设,过去没有被发现的问题,可能在新的网络环境、操作系统环境下,反而就变成漏洞。传统金融机构所特有的保守技术做派,未必是安全风控的最佳做法。以官僚化的OA慢流程来“风控”技术世界的快迭代风险可以理解,但过度的僵化同样带来高安全风险,例如你所依赖的某个异常古老的开源组件A,忽然因为A自己或者A所传递依赖的上游组件被黑客挖出了安全漏洞,需要紧急升级A最新的版本,可是你的应用软件太老无法兼容A的新版本,也就等于被活活噎死,无计可施。

白名单是否必要?由什么部门职能来维护?软件进出白名单的审核流程是怎样的?在一个拥有数千工程师的大型机构里,如何有效贯彻?对于采用了不在白名单上的开源技术的软件厂商和开发商,作为甲方要提供怎样的合理政策?这些问题都是企业必须梳理回答的。