Hotdry.

Article

DUSK 区块链 PLONK 证明伪造漏洞:未验证评估如何摧毁隐私层

深入分析 dusk-plonk 中四个未被绑定的选择器评估如何导致零知识证明被伪造,以及对 DUSK 隐私交易层的实际影响。

2026-05-03security

2026 年 4 月 30 日,区块链安全团队 OtterSec 披露了一个影响 Dusk Network 隐私交易层的严重安全漏洞。该漏洞位于 dusk-plonk PLONK 证明系统的验证环节,允许攻击者伪造有效的零知识证明,从而在无需任何真实资产的情况下铸造 DUSK 代币并转移非法所得的隐私资产。在漏洞披露时,DUSK 的市值约为 6000 万美元,整个 Phoenix 隐私交易路径处于风险之中。

漏洞的技术根源

Dusk Network 是一个专注于隐私保护的 Layer 1 区块链,其交易模型分为两种模式:Phoenix(隐私模式)和 Moonlight(透明模式)。Phoenix 模式下,所有交易参与者和金额信息均通过零知识证明进行隐藏,每笔 Phoenix 交易都必须携带一个 PLONK 证明来验证交易的有效性。这些证明的验证工作由 dusk-plonk 库完成,而该库自 2019 年 PLONK 论文发表同年就开始开发,是最早实现的 PLONK 库之一。

PLONK 证明系统的安全性建立在一个核心不变式之上:进入最终验证方程的每一个标量值都必须满足以下条件之一 —— 由验证者从公共数据本地计算得出、由证明者提供但附带 KZG 开放证明与先前承诺绑定、或者直接使用验证密钥中的承诺本身。任何违反这一不变式的情况都会导致证明系统的声音性(soundness)完全崩塌。

然而,dusk-plonk 的实现偏离了这一原则。在证明生成阶段,证明者将四个选择器评估值嵌入到证明结构中:q_arith_eval(算术选择器)、q_c_eval(常量选择器)、q_l_eval(左选择器)和 q_r_eval(右选择器)。这些值代表选择器多项式在随机挑战点 z 处的评估结果。在标准 PLONK 架构中,选择器多项式是公开的电路描述,本应通过预处理阶段承诺并存储在验证密钥中,验证时需要通过 KZG 开放证明来验证这些评估值与承诺的一致性。

问题在于,dusk-plonk 的验证逻辑直接消费了这四个选择器评估值,却从未将它们纳入 KZG 批量开放检查中。这意味着证明者可以任意设置这些值,而验证者会照单全收。验证依赖图中,安全的值会通过开放路径流向最终配对检查,但这四个选择器评估值直接进入了验证逻辑而无需任何加密绑定。

漏洞利用的数学机理

漏洞利用的关键在于,由于四个选择器评估值是自由的,证明者可以将验证方程转化为一个可以在事后求解的线性方程。在遵循诚实协议完成所有承诺轮次并推导出相同的挑战值后,证明者在看到 z_challenge(随机挑战点)后,计算线性化多项式在 z 处的实际评估值,然后反推出使验证方程通过所需的 q_arith_eval 值。具体而言,攻击者可以将 q_c_eval、q_l_eval 和 q_r_eval 设为零,仅求解 q_arith_eval 这一个自由变量,通过一次域上的除法运算即可完成。

这个攻击的技术本质是:证明者提交任意的见证多项式和商多项式,无需真实的见证数据,只需要构建一个形式上正确的证明结构,然后利用选择器评估值的自由度来满足最终验证方程。由于 KZG 承诺的同态性质,小的随机线性多项式就足以构造出所需的商多项式。

对 DUSK 生态系统的实际影响

在 Dusk Network 的实际运行中,Phoenix 交易路径承载了多个关键操作:隐私转账、质押、奖励提取、解除质押以及 Phoenix 到 Moonlight 的转换。每笔 Phoenix 交易都需要通过 verify_proof_with_version () 函数进行 PLONK 证明验证,只有通过验证的交易才能被接纳到内存池并打包入区块。

该漏洞的影响是全方位的。首先,攻击者可以通过伪造不存在的输入票据来凭空创造 DUSK 代币,这些伪造的票据声称具有任意金额,但从未在票据树的默克尔根中出现过。伪造的证明会说服网络这些票据是真实的,攻击者由此铸造出无限量的 DUSK。其次,攻击者可以伪造绕过所有权、成员资格和余额检查的隐私支出,这些伪造的隐私交易与合法交易在协议层面完全无法区分。由于 Phoenix 的隐私特性,一旦伪造的输出被接受到隐私资产池中,事后将几乎无法追溯,这与此前 Triton VM 漏洞对 Neptune Cash 的影响类似。

安全研究人员在一个本地 Dusk 测试网上进行了完整的端到端攻击演示:设置一个诚实的 Rusk 节点和两个钱包(诚实和恶意),初始余额均为零;恶意钱包使用伪造的 PLONK 证明创造出 2000 DUSK;恶意钱包通过一笔正常(诚实验证)的交易将 1337 DUSK 转移到诚实钱包;诚实节点验证了这两笔交易并将它们打包出块;最终诚实钱包显示了确认的 1337 DUSK 余额。

漏洞修复与行业启示

dusk-plonk 团队在收到漏洞报告后仅用一天时间就完成了修复。修复方案将四个选择器评估值添加到 KZG 批量开放检查中,使它们与验证密钥中已存在的选择器承诺进行绑定。具体修改包括:扩展 prover 端的 compute_aggregate_witness 函数以包含 q_arith、q_c、q_l 和 q_r;在 verifier 端的 E_evals 结构中添加这些评估值,使其在验证时与对应承诺进行校验。该修复于 2026 年 2 月 14 日提交,并在 2026 年 2 月 27 日通过 dusk-rusk-1.6.0 版本公开发布。

值得注意的是,该漏洞在多次审计中均未被发现。dusk-plonk 曾在 2023 年 12 月接受审计,Phoenix 在 2024 年 9 月接受审计,Rusk 节点库也在 2024 年 9 月接受了 Oak Security 的审计。然而,这个漏洞隐藏在一个非常容易产生的心智模型错误背后:标准 PLONK 模型中,选择器是公开的电路描述,审查者会自然地认为选择器在验证者端处理,从而忽略了 Dusk 实现中验证者开始消费证明者提供的选择器评估值这一架构偏差。

这个案例揭示了零知识证明系统实现中的一个系统性风险。OtterSec 团队在调查过程中还发现了 Espresso Systems 的 Jellyfish 库中存在类似问题,该库实现了 UltraPlonk 扩展,在 Plookup 查找参数的 15 个多项式评估中,有 9 个未被正确添加到 Fiat-Shamir 变换中,导致这些评估值可以在事后调整以满足验证方程。该问题同样通过一次域除法即可利用。Jellyfish 的修复在 2026 年 3 月 18 日合并并标记为 jf-plonk-v0.8.0 版本。

两个独立实现中出现同一类漏洞的事实表明,这不是一个仅靠审计就能解决的问题。检查代码中每个评估结构字段并确保其要么出现在开放证明批次中,要么由验证者本地计算 —— 这种检查本质上是机械化的,完全可以集成到开发工具、CI 流水线或标准化的 PLONK 验证规范中。当前每个团队都从论文出发实现自己的 PLONK 变体并希望审计者发现遗漏的模式是脆弱的,建立一个与曲线无关、与后端无关的验证协议规范,使评估绑定等不变式明确且可检查,才是解决这类问题的长期方向。

资料来源:OtterSec 博客文章《Commitment Issues: Unverified Evaluations in Dusk's PLONK》(2026 年 4 月 30 日)。

security