
850万台电脑因一个你这边无人审查的文件而崩溃
2024年7月19日早餐时分,一位在中型航空公司负责安全工作的朋友给我发来一张照片。那是一块航班信息牌,只不过每一格面板都是同样的蓝色,同样的白色错误文字在整个航站楼里一格接一格地重复。他没有配任何文字。他也不需要配。
等我喝完咖啡,这个数字已经变成了850万台Windows机器,在不到九十分钟内全部崩溃。不是恶意软件。不是零日漏洞。只是CrowdStrike的一次例行内容更新——这些公司专门花钱请这家厂商来保障自己的安全。本该保护端点的东西,正是把它们变成砖块的东西。
从那时起,我一直在构建本应处于这些厂商与这些机器之间的那一层——也就是我们现在所说的软件更新部署完整性,即厂商更新管线与你的生产机群之间的一道独立检查关卡。这篇文章要谈的是:为什么这一层此前并不存在,为什么最显而易见的构建方式是错的,以及当那块蓝色信息牌亮起的那一刻,每一家运行内核级代理的企业底下究竟发生了什么变化。
第21个字段

这份CrowdStrike的《外部根因分析》在2024年8月发布的当晚我就读了,那个原因小得几乎让人觉得受辱。
Falcon是CrowdStrike的传感器,它通过一种称为快速响应内容(Rapid Response Content)的机制来投递检测逻辑——这是一些小型配置更新,让它无需推送整个新二进制文件就能应对新威胁。7月19日,它推送了两个用于进程间通信检测的新模板实例。这些实例引用了第21个输入参数。CrowdStrike基于云端的内容验证器根据新的21字段模式对更新进行了校验,认定它有效,于是予以批准。
问题出在运行于Windows内核内、位于Ring 0(操作系统最高权限层)的内容解释器上。它仍然预期只有20个字段。当它去读取第21个字段时,读到了一块并不存在的内存,机器随即立刻蓝屏。
云端验证器依据新规则批准了一次更新。而接收更新的内核仍然遵循旧规则。没有人在检查这两者是否一致。
作为工程师,最让我耿耿于怀的是下面这一部分。崩溃发生在启动序列极其早期的阶段,以至于Falcon自己的管理代理根本没能启动起来。于是这些端点无法接收CrowdStrike推送出来的回滚命令,因为本该接收该命令的软件,正是让机器崩溃的那个东西。业界给这种情况起了一个阴森的名字——死代理循环。恢复不是按一个按钮。而是要靠人,逐台机器地进入安全模式,导航到C:\Windows\System32\drivers\CrowdStrike\,然后手动删除有问题的C-00000291-*.sys文件。达美航空在4万台服务器上都这么干了一遍。恢复花了五天。
问题从来不在于某一家厂商
简单的说法是CrowdStrike太粗心。但这也是错误的教训,若去追这个方向,只会引导我做出错误的产品。
因为这种模式并非CrowdStrike独有。调出任何一家大型企业的端点清单,你都会发现有八到十二个代理在内核级别或以提升的权限运行——EDR代理、数据防泄露代理、加密代理、补丁管理代理、VPN客户端、设备管理代理。表格上八行,就是八条各自独立的更新通道,各自按自己的节奏推送,各自被放行。
那个夏天我不断向各家CISO问同一个问题:在这些厂商更新触及生产环境之前,谁来审查它们?每一次得到的答案都是某种版本的我们有一个变更咨询委员会。然后,隔了一拍,才说出诚实的那部分:变更咨询委员会会逐行审查内部部署,但厂商更新会跳过工单队列、跳过预演环境,直接抵达每一个端点——因为“我们信任这家厂商”。这句话曾是整个行业的承重结构,而它背后却没有任何机制。
还有第二种几乎无人谈及的故障模式,而且它诊断起来更糟糕。当两家厂商在同一天更新内核接口时,它们的驱动可能发生冲突,产生与单一厂商漏洞一模一样的蓝屏。只不过这时根因分析要花几周而不是几个小时,因为你得在两家厂商的支持团队之间做三角定位,而他们各自——也算合情合理——都把责任推给对方。
我们最先做出的版本,以及它为什么失败了
刚开始时,我确信答案是检测。盯着端点,学习正常的样子,一旦更新开始异常就立即报警。这是整个可观测性市场训练我们养成的本能——Datadog、Dynatrace、Splunk,都极其擅长告诉你刚刚发生了什么。
我们做了这样一个版本。我们用一段更新驱动型故障的回放来运行它。它奏效了,只是奏效的方式极其无用:它把问题捕捉得漂漂亮亮,却是在头几台机器已经宕机之后。
我记得这一切落地时的那通电话。一位试点CISO看着我们的仪表盘在一次模拟的糟糕上线开始几秒后就亮了起来,大意是说,他不需要一种更快得知自己已经着火的方式。他需要的是让更新一开始就不要同时抵达他所有的端点。对于一个九十分钟就能击垮850万台机器的故障,部署之后才做检测,就像一个等房子烧没了才响起来的烟雾报警器。
可观测性告诉你大楼正在燃烧。到那时,唯一剩下的问题就是重建要花多少天。
那个月我在暗地里把工作押在了错误的一层上,而看着那块仪表盘印证这一点,是发生在我们身上最有用的事。问题从来都不是检测的速度。而是在更新抵达之前根本没有任何检查关卡。
那么,为什么现有工具捕捉不到这种情况?

人们以为软件供应链安全已经覆盖了这一点。它并没有,而原因是很精确的。
SBOM和软件成分分析工具——Snyk、Sonatype——审计的是你的开源依赖树。它们的设计目的是告诉你某个深达三层的npm包存在已知漏洞。但一家厂商的快速响应内容、一个通道文件、一个由CrowdStrike或任何同类厂商签名并推送的专有配置块——这些对它们而言是不可见的。它不在你的依赖树里。它是绕过依赖树被推送的,径直进入内核。那些本该保护你软件供应链的工具,审计的完全是错误的一层。
ITIL和你的变更咨询委员会呢?那是流程性的。它们是为你自己发起的变更设计的清单和审批,而它们从来没有与厂商的发布节奏对接过。
而CrowdStrike自己的补救措施——自恢复模式、内容固定、分阶段的“客户部署控制”、一套借鉴自CISA的“设计即韧性”框架——是实实在在的工作,我并不轻视它。但看清它究竟是什么:其中每一项控制都是厂商自我监管。推送了第21个字段的那同一家公司,如今也是认证它已经安全的那一家。在厂商的推送与你的端点之间,仍然没有任何独立的第三方。事故发生后的那个季度,CrowdStrike的总留存率仍在97%以上,这告诉你市场并没有惩罚他们——却完全不能告诉你底层的那个缺口是否被弥合了。它并没有。
那个缺口就是整个产品所在。正确的立足点既不在端点上盯着火情,也不在厂商内部听信他们的一面之词。它在两者之间:一道厂商中立的检查关卡,在更新抵达生产环境之前就把它接住,让它经过一个镜像你真实机群的沙箱,根据你的内核实际预期什么来校验其内容,并在其有误时对波及范围进行建模。这就是我们最终构建的那一层,你可以在我们的解决方案页面上看到它的形态。像21对20字段那样的模式不匹配漏洞,正是一个部署前沙箱会在金丝雀环里暴露出来的那一类问题,而不是让它一次性波及850万台机器。
法律根基已经移动,而大多数合同还没跟上
有一阵子我把监管这一面当作背景噪音。我错了,而买家们让我明白了原因:他们抽屉里的那些合同,已经不再按他们以为的方式保护他们了。
先看达美航空诉CrowdStrike案。2025年5月,在富尔顿县高等法院,埃勒比法官准许就重大过失、计算机侵入和不作为欺诈的诉求继续推进——越过了CrowdStrike合同中的责任上限。其中计算机侵入这一项,是应当让每一位CISO正襟危坐的:达美已经选择退出了自动更新,而那个通道文件仍然抵达了内核。如果一家厂商能够通过一条你的设置管不到的通道把Ring 0内容推送进来,那么你协议里的更新偏好设置可能就是无法强制执行的。大多数企业主服务协议(MSA)甚至根本不区分一次完整的传感器更新与快速响应内容。它们本应区分。
接着欧盟出手了,而这正是我如今在每一次亲自参与的合同重新谈判中都会提出的部分。修订后的《产品责任指令》如今明确将软件归类为严格责任下的一种“产品”,并规定企业不得以合同方式排除对软件和网络安全缺陷的责任。你的厂商在合同里圈出的那个几百万美元的责任上限,在欧盟司法辖区内可能根本站不住脚。与此并行,欧盟《网络韧性法案》将于2026年9月11日起强制要求上报漏洞——一个24小时的倒计时,而关键在于,它是从你知晓时开始计时,而不是从厂商通知你时开始。一家厂商的事故可能会很快变成你自己的上报义务。
而在美国,SEC如今要求上市公司在四个工作日内披露重大网络安全事件,并在其10-K文件中描述软件供应链风险。用成本数据算一算:New Relic在2025年9月发布的研究把重大IT停机的中位成本定在每小时200万美元,而41%的中大型企业给出的自家数字介于每小时100万至500万美元之间。一次由厂商更新引发、而你的变更委员会从未见过的四小时停机,仅凭其自身就越过了重大性门槛。你的投资者关系团队需要的是一份厂商事故应对预案,而不仅仅是数据泄露应对预案。
一次由你这边无人审查过的更新引发的四小时停机,按中位数计算大约要花费800万美元——这是那种会摆到CFO桌上、而不是CISO桌上的数字。
“这会发生在我们身上吗?”
2024年7月之后,全世界每一个董事会都向自家CISO问了同样的这几个字。而我聊过的CISO大多拿不出一个有条理的答案——这并不是在指责他们。IANS Research在2026年初的数据发现,只有29%的董事认为其CISO的安全汇报“非常有效”,而更新部署风险恰恰是那种真实存在、代价高昂、却几乎无法用大多数团队现有工具去量化成一个数字的东西。
那是我们所构建之物中更为沉静的另一半。不只是那道技术上的检查关卡,还有那个把“这会不会发生在我们身上”转化为一个可供董事会使用的答案的东西:一份囊括每一个特权代理及其更新通道的清单、一个针对每家厂商的量化波及范围模型、一份关于哪些更新经过了沙箱以及它们在其中做了什么的记录。它把一张过去写着“我们信任我们的厂商”的幻灯片,转化成一张展示实际工作的幻灯片。
有人问我,既然微软正把安全厂商推出内核——Windows韧性计划,配合快速机器恢复以及把端点安全从内核模式逐步迁移到用户模式——这一切现在是否还真有必要。这确实是一次结构性的良性转变,随时间推移它会缩小最严重的波及范围。但整个时间表要贯穿2026年和2027年,你在迁移中途的整个窗口期都会在运行一个混合机群,而“不那么灾难性”并不等于“已经过验证”。一个推送了糟糕配置的用户模式代理,仍然可以让它所负责的东西宕机。对独立检查的需求,并不会随着内核的消失而消失;它只是往上移动了一层。
人们说的另一件事是,加一道检查关卡会让一切都变慢——毕竟快速响应内容的全部意义就在于面对活跃威胁时的速度。有道理。但这个选择从来都不是速度对安全。CrowdStrike的云端验证器运行得很快,却仍然批准了那个有缺陷的更新,因为它拿文件去对照新模式做了校验,却从来没有校验内核是否与之一致。速度并不是那个失败之处。缺少一道独立检查才是。一个在30台机器上就能捕捉到模式不匹配的金丝雀环,只花你几分钟。而另一种做法让达美付出了五天和5.5亿美元的代价。
那块蓝色信息牌究竟意味着什么?
我一次次回到我朋友拍的那块航班信息牌的照片。在那一个上午里,每一家企业赖以生存的那个抽象——我们信任的厂商保护着我们的安全——被以字面意义的蓝色一格接一格地渲染了出来,就在一座挤满了滞留旅客的建筑里。
厂商们失败,并不是因为他们鲁莽。他们失败,是因为我们,作为一个集体,构建了这样一个行业:来自单一供应商的单一配置文件,能够在没有任何独立第三方核对其中数据的情况下,一次性抵达每一个端点。CrowdStrike只是那个恰好中签的。让这一切得以发生的那种结构,此刻正静静地躺在你能叫得出名字的几乎每一家公司的端点清单里——八到十二个特权代理,八到十二条通道,中间没有任何人。
你可以在这里读到我们所构建的那道检查关卡的完整架构。但我希望一位CISO带走的那部分,比任何产品都更简单。下一次这种规模的事故,不会以安全事件的形式宣告自己的到来。它会带着签名、带着信任、带着批准降临——与上一次的方式一模一样。唯一能改变结局的,是有人站在推送与生产机群之间,在全部850万台机器一次性发现问题之前,去核对更新与机器是否仍然一致。

