跳至正文

软件供应链安全 · 2026.10.24

企业的软件安全边界,不在采购合同上

从 PHP 严重漏洞出发,讨论企业如何把软件依赖清单⁠、影响判断⁠、处置权限与运行验证接起来⁠。SBOM 是起点,补丁发布不是终点,未知也不应被算成安全⁠。

一份 PHP 严重漏洞公告发出来,“我们的主要系统不是用 PHP 写的”,并不是足够的排除依据⁠。

企业没有直接选择一种技术,不代表它没有进入企业的系统⁠。它可能被第三方产品带进来,也可能作为运行环境,支撑着业务团队根本看不到的功能⁠。荷兰国家网络安全中心 NCSC-NL 为 PHP2Shell 建立的资料库,就包含对依赖或嵌入 PHP 的第三方产品的排查信息⁠。[1]

看企业使用的软件,至少需要三个视角:自己写了什么,向别人购买或委托开发了什么,以及这些软件底下还依赖什么⁠。

第三层并不是独立于前两层的另一堆软件⁠。它就在前两层里面:操作系统⁠、语言运行环境⁠、开源组件⁠、基础镜像,以及它们继续依赖的其他组件⁠。

采购记录回答的是“买了什么”,依赖关系回答的是“它靠什么运行”⁠。这不是同一张清单⁠。

合同当然重要⁠。它可以约定谁提供信息⁠、谁交付补丁⁠、谁承担支持工作⁠。但技术影响范围不能只靠合同判断⁠。一个组件出了问题,需要沿着依赖关系查到实际系统,而不是查到供应商名称就停下⁠。

一⁠、清单的终点,不应该是组件名称

SBOM,也就是软件物料清单,可以帮助企业了解软件由哪些组件组成⁠。它是软件的“成分记录”,不是一张自动覆盖企业所有业务⁠、部署位置和责任人的总表⁠。[2]

因此,“已经向供应商收集了 SBOM”只能算起点⁠。还要把它接到资产管理和漏洞管理中,才能从一条漏洞公告反查哪些已部署产品包含相关组件⁠。CISA 等机构的 SBOM 使用指南,描述的正是这种连接方式⁠。[3]

落到企业管理上,可以再多追问一步:查到一个组件之后,接下来能找到谁⁠?

假设清单显示某个产品包含 PHP⁠。企业还需要知道:这个产品部署在哪里,是否仍在使用,哪些入口对外开放,承载什么业务,由哪个团队维护,谁能决定临时限制访问⁠。

如果这些关系没有连起来,安全团队收到的只是一个技术名词,业务团队收到的只是另一封待转发的邮件⁠。

清单也不该只在交付验收时出现⁠。软件版本⁠、实际部署和维护责任发生变化时,应当一起更新相关记录⁠。否则,文件可以很完整,却未必能回答生产环境此刻的情况⁠。

有用的清单,应该让一个漏洞最终对应到一个可处置的系统,而不只是对应到一行组件名称⁠。

二⁠、“有这个组件”和“这套系统受影响”,中间还差证据

找到组件之后,不能立刻得出两种极端结论:既不能一律宣告系统可被攻击,也不能因为暂时没有发现攻击,就认定没有风险⁠。

CISA 的 VEX 技术文件把漏洞状态区分为受影响⁠、不受影响⁠、已修复和调查中;“不受影响”需要相应的理由或影响说明⁠。这种区分提醒我们,组件清单和影响结论不是同一件事⁠。[4]

以此次 PHP 漏洞为例,官方在 2026 年 10 月 21 日发布的修复版本是 8.2.35⁠、8.3.36⁠、8.4.27 和 8.5.12,对应两项可导致未认证远程代码执行的严重漏洞⁠。10 月 23 日,官方又对一种罕见的会话配置与运行时切换组合发布了额外风险提示⁠。[5]

这意味着,排查不能停在抄下一组版本号⁠。还要核对公告对应的漏洞⁠、实际产品⁠、部署方式和适用条件⁠。

版本号本身也需要解释⁠。部分发行商会把安全修复移植到仍在维护的旧版本,这叫 backport⁠。Red Hat 明确说明了这种做法⁠。因此,看起来低于上游修复版本的厂商包,不一定没有修补;反过来,“厂商应该做过回移”也不能代替证据⁠。需要核对具体包版本与厂商的安全说明⁠。[6]

对于尚未拿到证据的系统,最诚实的状态是“调查中”⁠。

不知道供应商是否使用了 PHP,不是没有使用⁠。没有收到漏洞通知,不是已经确认不受影响⁠。供应商一句“正在评估”,也不等于企业可以停止追踪⁠。

“未知”应当带着负责人和下一次确认时间,而不是在汇报中被悄悄算成“安全”⁠。

三⁠、快速响应,先要有人能决定付出什么代价

知道系统受影响,并不自动意味着企业已经能够行动⁠。

假设一个对外服务需要修补:技术团队可以准备升级,但升级可能需要短暂停机;业务团队不愿影响订单,供应商还没有完成验证⁠。此时缺少的,未必是另一条技术建议,而是一个明确的决策人⁠。

谁能批准临时关闭高风险入口⁠?谁能接受短时间服务降级⁠?如果暂缓升级,谁确认剩余风险,又在什么时候重新评估⁠?

这些问题应该在平时就有答案,而不是在应急会议里临时寻找有权拍板的人⁠。

针对本次 PHP 事件,CERT-EU 建议立即修补受影响资产;无法及时修补时,应考虑将面向互联网的应用隔离出公共网络,直到修复应用并验证⁠。[7]

这里的重点不是“所有系统一律停机”,而是不能把“暂时不能升级”理解成“暂时不必做任何事”⁠。应根据具体暴露面⁠、业务影响和官方建议,选择可行的临时措施,并明确它们的限制⁠。

临时防护是为了争取处置时间,不应该成为无限延期的理由⁠。等待补丁,也应当是一项有人负责⁠、有复核时间的决定⁠。

四⁠、“补丁装上了”之后,还有一次真正的验收

供应商已经发布⁠、运维已经安装⁠、工单已经关闭,描述的是不同环节⁠。它们都不能单独替代对当前运行状态的确认⁠。

NIST 的企业补丁管理指南把验证明确纳入流程:不仅确认补丁安装,还要确认已经生效;根据具体情况,可能需要重启软件⁠、重新部署或调整配置,并持续确认防护没有被撤回⁠。[8]

因此,一份有说服力的修复记录,应该能回答:哪些运行实例已采用修复,哪些仍未完成;关键业务是否正常;临时防护是否仍有保留必要;如果发生回滚,是否会把未修复版本重新带回来⁠。

验收对象应当是正在承载业务的环境,而不是一条成功结束的安装命令⁠。

还要把另一个问题单独拎出来:系统在修复之前,是否已经遭到入侵⁠?

微软在 2021 年 Exchange 事件的官方处置指南中明确指出,安装安全更新不会驱逐已经进入系统的攻击者⁠。这里借用的是处置原则,并不是认定本次 PHP 事件中的某套系统已被攻击:发现或怀疑入侵时,漏洞修复与事件调查需要并行,不能拿补丁成功替代调查和清除⁠。[9]

修补的是入口,调查的是过去发生了什么,恢复确认的是现在还能不能信任这个环境⁠。三者不能互相代替⁠。

五⁠、把供应商的交付,接到企业自己的行动上

落地时,可以把责任设计得具体一些⁠。

供应商需要说明产品是否受影响⁠、依据是什么⁠、哪些版本包含修复,以及部署和回退有哪些限制⁠。企业内部则需要有人确认实际使用范围⁠、安排变更⁠、验证结果,并处理尚不能修复的例外⁠。具体分工可以不同,但中间不能出现无人接手的空白⁠。[10]

“这是外包系统”应该帮助我们找到正确的处理路径,而不是让问题停止流转⁠。

同样,已经停止维护的产品,不宜只留下一条“暂不升级”的备注⁠。可以要求每个例外都有当前防护⁠、明确负责人⁠、复核日期,以及替换或退出的计划⁠。这是一种管理选择,不是说所有旧系统都必须立即停用⁠。

如果要检验这套机制是否真的存在,不必先检查流程图画得多完整⁠。可以选一条真实漏洞,沿着它走一遍:

走到哪里必须重新打听,哪里就值得优先补齐⁠。

企业不可能亲自编写⁠、审查和维护所使用的每一行代码⁠。但至少应该知道,关键业务依赖什么,出现问题后由谁处理,处理完毕又凭什么确认⁠。

安全管理真正需要连起来的,不是“公告—邮件—工单”,而是“依赖—影响—决定—运行结果”⁠。

下一次重大漏洞出现时,企业应该是在使用这条已经建立的路径,而不是第一次开始寻找:到底谁在用这段代码⁠。

我的观点

技术影响范围不能只靠采购或外包归属判断⁠。企业需要把依赖⁠、影响⁠、决定与运行结果连起来,让每个风险都有可追踪的处置路径和完成证据⁠。