Log4j 那天晚上我在客户现场2021 年 12 月我记得很清楚那天我正在银行客户现场做交付。下午四五点的时候客户的安全团队突然在群里炸了Log4j 出了一个远程代码执行漏洞CVSS 满分 10 分影响范围极广。攻击方式简单到离谱——用户在输入框里敲一行${jndi:ldap://xxx}你的服务器就能被别人接管。不用登录不用提权直接 RCE。然后接下来的事情我估计很多人都经历过安全团队问开发我们系统里有没有用 Log4j开发说应该有吧我查查。这一查就是好几天。客户的核心交易系统大概有 200 多个微服务分属不同业务线不同时期由不同团队搭建。有的用 Spring Boot有的用 Dubbo有的还是老项目。每个服务的 pom.xml 里都塞了一堆依赖谁也说不清 Log4j 到底被哪些服务直接或间接引用了。最后怎么解决的安全团队逼着每个服务的负责人自己去翻 pom.xml一个一个查。折腾了将近一周才勉强拉出一份受影响服务清单。然后呢升级 Log4j 版本半天搞定。找漏洞花了一周修漏洞花了半天。那天晚上回酒店的路上我就在想这不对。问题不在于怎么修而在于去哪找。如果连自己系统里用了什么都不知道谈什么安全治理后来我见得越多越确信一件事——这不是某一家银行的问题几乎所有企业都处于同样的状态你的软件供应链实际上是失控的。你的代码里大部分不是你写的后来我做了一个统计那个银行客户 200 多个微服务的代码仓库里开源代码占比平均在 70% 以上有几个老系统甚至超过 85%。这不是个例。Synopsys 2023 年审计了 1700 多个代码库发现96% 的代码库包含开源组件76% 的代码是开源代码。Veracode 的数据更狠——97% 的 Java 应用完全由开源组件构成。也就是说你花了几百人年搭起来的系统大部分砖是别人免费给的。这本身不是问题开源组件让软件开发效率提升了不知道多少倍。问题在于——你用了别人的东西但你不知道你用了什么。这就像你盖了一栋楼用了 200 家供应商的材料但没有任何一份材料清单。有一天有人告诉你3 号供应商的钢筋有质量问题你连这栋楼里哪些地方用了他家的钢筋都查不出来。这就是所谓的失控。我在项目里见过的三种失控场景场景一漏洞来了全公司翻箱倒柜除了 Log4j我还经历过好几次类似的事。有一次安全团队通报 Fastjson 某个版本存在反序列化漏洞。我们赶紧去排查发现系统里至少有 30 多个服务用了 Fastjson。但问题是——版本号五花八门有 1.2.37 的有 1.2.68 的还有几个服务用的是 1.1.x 的老古董。更头疼的是有些服务不是直接引入的 Fastjson而是通过某个二方库间接带进来的。开发自己都不知道自己用了 Fastjson。你让开发一个个去查效率极低而且容易漏。漏掉一个就是一个安全隐患。你连有什么都不知道怎么防场景二问谁都不知道的历史遗留还有一个场景特别常见。系统里有个工具类引用了一个叫commons-collections的 Apache 组件。这个组件的某个老版本有反序列化漏洞。我们要不要升级升级了会不会影响现有功能问了三个开发三个说法不一样第一个说这个组件是我前任留下的我也不知道为什么用这个版本。第二个说升级过一次但是测试环境跑不通又回滚了。第三个说这个类好像没什么地方在用但不敢删。你看一个组件三个人三个态度没有一个人能给出确定答案。最后只能先标记为风险已知暂不处理——说白了就是搁置。搁置不是解决了是假装不存在。场景三你下载的开源包可能已经不是原来的了2024 年出了一个大事件不知道你关注了没有。有个叫xz-utils的开源项目是几乎所有 Linux 系统都默认安装的压缩工具。有个叫 Jia Tan 的人从 2022 年开始给这个项目提交代码补丁表现得很积极慢慢获得了项目的维护权限。然后他在 2024 年发布的 5.6.0 和 5.6.1 版本里悄悄植入了一个后门。这个后门的目标是什么劫持几乎所有 Linux 服务器的 SSH 登录。如果不是微软的一个工程师偶然发现 sshd 登录速度变慢了顺藤摸瓜查到了 xz-utils 的问题这个后门不知道会被埋多久。这事儿细思极恐的地方在于xz-utils 是一个有十几年历史、被全球无数系统依赖的基础设施级项目。攻击者不是从外面攻破的而是从内部渗透进去变成了维护者。你用的开源组件可能已经不是原来的那个组件了。但你不知道。你连变没变都感知不到这叫什么失控。靠 Excel 管依赖别逗了说完问题说说很多企业现在的做法。最常见的是让开发自己报。每次引入新组件填个表写明组件名、版本号、用途。听起来很合理对吧现实是开发忙着写业务代码填表这件事优先级永远排在最后。报上来的信息也不靠谱——版本号写错了、间接依赖没报、升级了忘了更新记录。半年后你去看那份表跟实际情况已经对不上了。还有用 Excel 维护的。我见过一个客户安全团队维护了一份巨大的 Excel 表记录了所有系统的开源组件信息。但是——系统 A 升级了一个依赖版本Excel 没更新系统 B 新引入了一个组件开发忘了报系统 C 重构了删了几个依赖没人知道三个月后这份 Excel 就成了一份历史文物——有记录价值但没有参考价值。靠人的主动性和记忆去管理动态变化的依赖关系注定管不住。SBOM 解决了什么首先解决一件事让你看得见SBOMSoftware Bill of Materials软件物料清单。概念不复杂说白了就是给你的软件出一份配料表——里面用了哪些开源组件、什么版本、从哪来的、依赖关系是什么。但它首先解决的是可见性的问题——让你看得见你的系统里到底有什么。还是拿 Log4j 举例。如果每个服务在构建的时候都自动生成了一份 SBOM存到中央仓库里那安全团队只需要在系统里搜一下 log4j30 分钟内就能拉出完整的清单哪些服务用了 Log4j用的是什么版本是直接引入的还是间接依赖带进来的每个服务的负责人是谁不用翻 pom.xml不用问开发不用猜。审计人员来检查问你们系统里用了哪些开源组件许可证合规吗没有 SBOM 的时候你得翻历史邮件、找各个团队收集信息、手动整理成表格搞上好几天最后还不一定全。有了 SBOM一键导出。什么组件、什么版本、什么许可证、谁引入的、什么时候引入的全部有据可查。把不知道变成知道把查不到变成一键搞定。从这个角度看SBOM 做的事情本质上不是列清单而是把原本不可见的软件依赖变成可以被管理的资产数据。但我要说句实话SBOM 解决的是可见性问题。但看得见只是第一步。我见过太多企业做了 SBOM、买了扫描工具、部署了自动化流水线觉得自己挺现代化了。但开源依赖还是管不好。为什么因为看得见不等于管得住。你看得见系统里有 30 个服务用了 Fastjson但开发就是不升级你怎么办你看得见某个组件的 License 有风险但业务说这个功能下周就要上线来不及换了你怎么决策可见性是基础但光有可见性你的系统依然是失控的。如果把这件事拆开其实至少需要三层能力第一层可见性——你知道系统里用了什么、有什么风险第二层控制力——你能管住团队怎么用、出了事怎么处理第三层决策能力——你知道该不该用、用哪个、什么时候换SBOM 解决的是第一层。但没有第一层后面两层都无从谈起。后面我会一篇一篇展开讲。不做行不行看政策说到这里可能有人觉得我们公司目前没出过事有必要搞这个吗我理解这种想法。但我想说两个事实2021 年美国政府发布了总统行政令 EO 14028要求所有向联邦政府交付的软件必须提供 SBOM。这不是建议是强制要求。中国也已经发布了 GB/T 47020《网络安全技术 软件物料清单数据格式》国家标准中国信通院已经启动了 SBOM 国标符合性验证工作。趋势很明确SBOM 正在从最好有变成必须有。尤其是金融、政务这些强监管行业早晚会面对这个要求。与其等审计来了临时抱佛脚不如现在就建起来。回到那个银行项目最后说说那个银行项目后来的变化。我们在交付过程中帮客户建了一套 SBOM 机制每次 CI 构建的时候自动生成物料清单推送到中央仓库。所有服务的开源组件信息实时更新不用人手工维护。效果很直观之前安全团队问系统里有没有用 X 组件48 小时答不上来后来同样的查询2 小时出结果之前合规审计准备软件成分清单几个人搞了好几天还经常漏后来一键导出之前新引入组件没人管出了事找不到责任人后来每个组件什么时候引入的、谁引入的、为什么引入全部有记录不是什么花哨的技术方案就是把看不见的东西变得看得见了。从失控到可控的第一步。