← 最新论文
💻 computer science

Four Ways to Forge a Bundle My Own Verifier Calls Clean: Refusal-Site Mutation Testing of an Evidence-Bundle Verifier

本文介绍了一项关于证据包验证器(evidence-bundle verifier)的自我审计研究,该验证器尽管通过了外部审计,却被发现存在“空洞通过”(vacuous pass)缺陷,即检查在未实际检查数据的情况下报告成功,作者通过使用一种自定义的拒绝站点变异测试框架(refusal-site mutation testing framework)系统地量化并消除了这一缺陷,从而实现了完美的检测得分。

原作者: Erik Hill

发布于 2026-08-28
📖 1 分钟阅读☕ 轻松阅读

原作者: Erik Hill

原始论文采用 CC BY 4.0 许可(http://creativecommons.org/licenses/by/4.0/)。 这是对下方论文的AI生成解释。它不是由作者撰写或认可的。如需技术准确性,请参阅原始论文。 阅读完整免责声明

在现代数字世界中,软件系统通常依赖于一个简单但强大的理念:信任,但验证。当一个计算机程序声称解决了一个难题或分析了一个海量数据集时,它会生成一份报告。为了确保这份报告是诚实的,其他程序会充当审计员。这些审计员会检查数学计算,验证数据文件是否被篡改,并确认摘要中的数字与原始证据是否一致。如果一切符合要求,审计员就会给出绿灯,并将结果发布给世界。这个过程是可靠软件的支柱,使得陌生人无需了解彼此也能信任彼此的工作。然而,为了让这个系统运作,审计员本身必须是完美的。如果审计员未能发现谎言,或者更糟的是,在没有实际查看证据的情况下就宣布谎言为真,整个系统就会崩溃。危险之处不仅在于坏的结果可能溜过去,而在于审计员可能由于过于脆弱,以至于在从未运行测试的情况下就通过了测试。

一位名叫埃里克·希尔(Erik Hill)的研究员着手研究这样一个审计员,该程序旨在验证用于离线系统的证据包。他想了解一个特定且令人不安的问题:这个程序在实际上并未进行任何检查的情况下,有多少次会说“通过”?为了找出答案,他不仅仅是在寻找漏洞;他构建了一个工具来系统性地破坏他自己的审计员。他逐一关闭了程序中所有原本应该拒绝错误包的代码行。然后,他观察测试套件是否会察觉到这一点。如果删除拒绝行后测试仍然通过,这意味着该拒绝行是多余的负担——它从未真正发挥过作用。结果令人震惊。在研究开始时,审计员三分之二的拒绝点对测试是不可见的。该程序可以被剥离掉大部分说“不”的能力,却依然能报告完美的分数。这就像是一个受过训练去检查失窃物品的安全警卫,但训练演习中从未包含过失窃物品,因此警卫从未学会如何去寻找它们。

这项研究始于一位外部专家的冲击。一名独立工程师提交了一个证据包,其中的标题数据完全错误,但审计员却打印出了完美的通过。这场欺诈仅耗费了四个字节即可完成。工程师用一个微小的、空的占位符替换了一个文件,由于审计员未能检查该文件是否真实存在,它便假设一切正常。希尔修复了这个特定的漏洞,但他随后将自己的系统化工具应用到了修复后的程序上。他发现问题不仅仅是一个错误,而是一种模式。他发现了另外四种欺骗审计员的方法,每次都发现程序正在跳过某项检查。其中一个技巧涉及更改严重性标签中的一个字母大小写,这导致程序忽略了失败检查的权重。另一个技巧涉及删除列表中的一个键,导致程序因为要比较的项目缺失而跳过了比较。在每种情况下,程序并不是未能进行一项艰苦的计算,而仅仅是未能开始这项计算。

为了衡量这一问题的普遍程度,希尔针对审计器的代码运行了他的删除工具。他发现有 112 个地方程序本应说“不”。当他逐一移除它们时,有 75 个可以在没有任何测试失败的情况下被删除。这意味着 112 个拒绝点中有 75 个实际上对系统的安全检查是不可见的。该程序的得分为 0.330,表明其大约只有三分之一的拒绝机制正受到测试。剩下的三分之二是“空洞通过”(vacuous passes)——即尽管从未检查证据,却报告成功的检查。这不是一个罕见的故障,而是一个结构性缺陷,即安全网上的漏洞从未有人尝试跌落其中。测试是在检查程序是否在运行,而不是检查它是否真的查看了数据。

希尔随后测试了一种解决此类问题的常见方法:仅仅修复发现的具体漏洞并为每个漏洞添加测试。他修复了发现的四个伪造点,并添加了新测试以确保这些特定的技巧不再奏效。令人惊讶的是,这并没有提高整体安全性得分。程序仍然拥有同样的 75 个不可见的拒绝点。新测试仅覆盖了他刚刚修补的那些漏洞,使得其余部分依然和以前一样盲目。只有当他改变策略时,数字才发生了变化。他不再仅仅是修复漏洞,而是为每一个不可见的拒绝点编写了一个新测试,强制程序证明它确实可以触发每一个点。这种系统化的方法将分数从 0.330 提升到了 1.000,证明了每一个拒绝点确实是可以被触发的。教训很明确:修复已知的漏洞并不能让系统变得安全;你必须证明每一个安全机制实际上都能发挥作用。

这项研究还揭示了这些系统构建方式中的一个深层问题。研究人员发现,审计员经常对人类可读的报告与用于检查的原始数据文件采取不同的处理方式。当一个证据包包含一份供人阅读的报告时,审计员经常无法验证该报告是否与底层数据相匹配。这就像是审计员信任摘要页,却忽略了收据。这种情况发生在多个不同的项目中,表明开发者中存在一种常见的习惯:他们绑定了计算机检查的数据,却让人类阅读的数据处于未经验证的状态。研究人员发现,这种差距允许虚假声明溜过,即一份报告可以声称“所有缺陷已修复”,而数据却显示并非如此。

在整个研究过程中,研究人员自己的工具也以镜像其所研究的问题的方式令他失望。他的测量仪器有时会在什么都没测量的情况下报告成功。在一次实例中,一个旨在检测失败的工具返回了完美的分数,因为基准测试套件已经失败,导致工具误将错误解读为成功。这种情况在研究期间发生了七次,包括一次工具在系统损坏时仍给出完美分数的时刻。这些失败并未被隐藏;它们被记录在论文中,以展示用于验证软件的工具本身也同样容易受到这些“空洞通过”错误的影响。

这项工作的最终结论是对一种不同类型测试的呼吁。研究人员认为,我们不能依靠一份已知漏洞的清单来保持系统安全。如果一个系统的安全闸门从未被观察到失效,那么它也从未被观察到有效工作。唯一的确定方法是系统性地测试每一个闸门,以确保它确实可以触发。研究表明,一个系统可以在纸面上看起来很完美,但在实践中却是根本性破损的。通过迫使审计员在每种可能的情况下都能拒绝错误数据,研究人员将一个对其自身失败视而不见的系统转变为一个经过完全验证的系统。这项工作提醒人们,在数字信任的世界里,最危险的错误不是检查失败,而是检查根本没有发生。

您所在领域的论文太多了?

获取与您研究关键词匹配的最新论文每日摘要——附技术摘要,使用您的语言。

试用 Digest →