找工位
空间入驻
小程序

让企业数字化砸锅和IT主管背锅的软件供应链安全风险指北

2022-07-07 00:00:00
文章转载自"ToB行业头条"


“恶意”这俩字,不仅在现实世界,在软件世界也是满满的。

来源  /   凡泰极客  (ID:finogeeks  

作者 /   F1n0Geek 



日前,「ToB行业头条」采访与报道过凡泰极客这家企业,感兴趣的朋友点击链接即可阅读:「小程序容器技术」,是噱头还是新风口?


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


某天,某银行被盗取大量数据、遭受巨大经济损失,并遭到消费者集体诉讼和监管天量罚单。


原因是技术系统用了某个开源代码包,该开源代码包原来是一个遭黑客污染过植入了后门的有毒组件。不小心误用这个代码包的,是IT部门某基层小弟所为。


新闻爆出,CIO一脸蒙圈,卒。


上述情形目前...暂时是,虚构的。会不会发生呢?概率不小。罪魁祸首,叫软件供应链攻击。这个问题的潜在风险,大到什么程度呢?


根据Gartner,至2025年全球有接近一半的企业会遭遇到。后果?对于企业数字化是巨大的爆雷,对于企业的技术高管,参照上述“CIO”。


今年初白宫都不得不召集会议讨论Log4J,拜登都得知道Java,是不是莫名魔幻?


但对于码农来说是不是略感自豪 - 相当于所在银行行长、公司CEO深入IT基层,亲自了解一个用Java写的、通常埋在十八层代码之下的日志工具,“并作出重要指示”的既视感...



接下来,本文尝试“贴心”的替百忙中未必有空学习了解“软件供应链”的领导们作一点点学习,总结一些科普性内容,描述一下问题、归纳一下挑战、整理一些概念、总结一些策略,但是难以高度浓缩,行文依然略长,感谢耐心读完的看官。


01

什么是软件世界的

“Supply Chain”


各行各业都有供应链,就像一家车厂,它生产整车,不可能从轮胎、车窗玻璃、车门把手做起。


正如物理世界的任何产业都有自己的产业链、供应链一样,在虚拟世界的软件业也一样,任何终极软件产品,都用到很多的虚拟“零部件” - 以代码库形态存在的组件、框架、工具,而且这些“零部件”本身也高度依赖其他“零部件”。


以银行为例,消费者、业务部门使用的软件,由银行的IT部门提供。但这些软件仅仅有小部分是IT自己开发的,更多是从第三方供应商采购。


而且,无论软件是自己开发,还是由系统集成商或软件厂商开发,都依赖于大量的更加基础的软件组件、项目、工具。


在这个时代,也许除了国防军工领域的软件,几乎不可能存在每一行代码都100%由自己开发的软件 - 工作量不允许、经济规律也不符合。


实际上,随便一个软件,按绝对代码行数来算,一个不小心有一半是第三方的,例如在一些微服务里,自己的代码只占10%,也一点都不奇怪。


02

“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... 不可胜数,都自带包管理工具、“零部件”中央仓库、以及庞大的开发生态。



上图为每年各语言新增软件包数量,其中npm生态2019年新增超过30万个。


上图缺乏新兴语言如Golang、Rust等的数据,但这些语言生态中的“零配件”数量的快速增长,对于开发工程师来说,都是可直接感知的。


相比之下,Java、Ruby的组件生态增长率较低,但很大程度因为它们已经增长了近二十年,基数已经极其庞大。


03

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


开源软件运动如火如荼的进行了二十四五年(如果从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)- 这就是计算机领域解决问题的一个典型的、最根本的思维方法。


这很好的解释了软件供应链的需要 - 从硬件、网络层、操作系统、虚拟化管理软件、中间件、开发工具、开发框架、前端组件、辅助代码库,到编译器、解析器、运行时,层层叠叠,每一层面对自己的领域、解决好自己的问题,最终到达面向终极用户的应用软件,再大的公司、再牛的工程师,都难以自己包打天下。


全球化和开源运动相辅相成,而软件技术人则在这个开源世界的“乌托邦”相互成就。


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


04

虚拟世界的供应链

远比物理世界的无序凌乱


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



产品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%确定的。


05

软件供应链的四大风险


企业的基层开发人员,往往并不关注(也难以有能力和工具去评估)自己的代码所间接、被动引用的第三方代码包的来源、质量、安全风险。


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


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


  • 软件质量风险。企业软件表面上由IT或者外包商开发,可是实质上背后是成千上万的第三方开源代码,企业的QA工程质量管理方法和流程,对于第三方完全失控无效。


  • 长期支持风险。企业软件所间接依赖的一些第三方开源零部件,并没有商业体在背后提供质量承诺和长期支持。开源项目因创始人退出或者社区活跃度低而不再维护、半途而废的,不在小数。

    产生维护支持需求时,企业自己不得不安排人手去处理该部分代码,先不说有没有这个意愿,企业自己的IT工程师是否有这个能力也难说。


  • 知识产权风险。开源软件的知识产权机制,反映在著佐权(Copyleft)和许可证(Permissive)。后者约束了你的软件的分发传播需要满足的条件,前者则往往更进一步要求你用开源组件开发的软件本身的源代码必须沿用同样的开源条款,导致你的软件知识产权不得不公开。
    国内软件企业在使用开源、贡献开源的过程中规则意识普遍薄弱,存在错误混用不兼容的许可证,违反许可证规定二次发布等问题,带来更为复杂的知识产权问题和法律合规风险。


  • 信息安全风险。在开发人员写第一行代码前,一个系统可能就注定继承了一堆“安全债务” - 部分取决于这个系统的设计者、开发者选择采用什么第三方组件,部分取决于这些第三方组件的开发者又选择依赖于什么别的组件。
    反正安全风险是传递的,只要有一个零部件有安全漏洞、甚至是在漫长复杂的互联网分发链路上被篡改过注入了恶意代码,你的系统就继承了所有这些风险。

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

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


06

Supply Chain Attack 

软件供应链攻击


在复杂混乱的软件供应链之下,黑客利用其中的漏洞进行安全攻击,从中渔利,是显而易见的。

当程序员在开发软件的过程中无知觉的使用了被恶意篡改的零部件,所开发出来的系统可以说天生就埋入了危险种子。

以前段时间闹的非常严重的Log4J远程代码执行漏洞问题为例,一个存在了近二十年、极其大量的为开发者采用从而在无数的互联网网站、企业软件、Web工具中运行的日志记录组件,让使用它的工程师做梦也想不到。

这类攻击,隐蔽性极高 - 你的代码不用Log4J不等于你所依赖使用的第三方代码或者它们所依赖的上游代码不用。

正因为其隐蔽性,大大增加黑客的兴趣,这一类攻击正在迅速增长,以至于拜登政府都不得不视之为严重危害。

随之而来是科技企业共同推动下,拜登政府成立开源安全相关的基金,以长期资助促进对安全漏洞的监控和修复。


根据Gartner的报告,到2025年全球将有45%的机构组织遭遇所谓的软件供应链攻击 - 是2021年的3倍。

这些攻击一旦成功,对于黑客而言经济利益巨大,对被攻击的企业则是摧毁性的 - 不仅危害运行遭受攻击的企业,更可能因为其商业数据、用户数据的丢失而延伸至损害受损企业的客户。

数字化世界里,安全攻击往往是有网络效应的、传染性的。

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

如果把汽车换成火车甚至军舰,可以想象所带来的灾难。

07

软件供应链里的“康帅博” 

Low但致命的那种


2021年初,有一位安全技术研究者兼白帽黑客叫Alex Birsan的,就发文详细描述了他如何通过一种叫Dependency Confusion的方法,把“恶意”(象征性但无害)的代码,“种入”到Microsoft、Apple、Uber、Yelp以及好些其他较为知名的公司的代码库(内部供应链)中,Alex成功“攻击”了35家企业,其中大部分拥有千人以上的员工规模。

Dependency Confusion的手法也不复杂,就是把含有恶意代码的软件包上传至npm、PyPi等互联网公共仓库,软件包名字和常用的开源包完全同名(或者就是在该开源代码上增加恶意代码,然后发布新版本,正常功能完全一样)

如果一些企业的内部开发环境有漏洞,其项目构建工具、集成工具并没有被妥善配置以保障完全从且仅从内部仓库拉取零部件,则很有可能会拉到公网上的同名中毒版本,然后神不知鬼不觉的种入了安全漏洞,当这样一套软件成本被销售、部署到客户那里,就是坐等配合外部黑客的攻击。

此外还有所谓Typosquatting的攻击,同样也不高级,把带有恶意代码的软件包发布至公共仓库中,包的名字和被仿冒的开源项目非常相似 - 往往就是少个字母(例如CoffeeScript被CofeeScript或者CoffeScript假冒)、多一道横杠(crossenv.js被cross-env.js假冒)... 嗯,就是“康帅博”、“奥利傲”、“六大核桃”这些李鬼玩法,不过危害严重到致命,这些软件包往往维持原有的功能,在你的软件系统中正常勤恳的工作着,但同时也默默的偷窃着你数据、充当着配合外部攻击的内鬼。

开源工作者在开源社区的账户也可能被盗取,毕竟开源工程师也是普通人,他们在账户安全的防护上也不见得就比寻常人更强,例如在GitHub上的开发账户被破解盗取,黑客也可以悄悄的替这个账户的主人在他的源代码里添上几行...

再有就是通过所谓social engineering的方法,恶意参与到一个开源项目的合作中,直接在上游污染其所间接依赖的某些其他开源组件。

开源社区因为成员有共同的对开放共享的理念认同,通常全心、热情拥抱参与者,这也给作恶者可乘之机。

总之,“恶意”这俩字,不仅在现实世界,在软件世界也是满满的。





推荐阅读

腾讯云的一场硬仗

中国SSD行业企业势力全景图

阿里打出「瓴羊DaaS」这手好牌

中国的软件公司为什么做不出产品?

ToB月报丨融资总金额达56.54亿;阿里、360、腾讯加快企业服务步伐