ZEC 漏洞事件学习记录
See Taylor’s full report and work log for details.
事件:安全研究员 Taylor Hornby 于 2026 年 5 月 29 日发现了 Zcash Orchard 资金池中的一个严重伪造(counterfeiting)漏洞。该漏洞位于 Orchard 的 zk-SNARK 电路内,破坏了一个关键的”可靠性(soundness)“属性——即阻止非法状态转移的属性。
后果是攻击者可以不被发现地伪造无限量的假 ZEC。值得注意的是,这个漏洞是 Taylor Hornby 通过一个自定义的审计 agent 框架配合刚发布的 Opus 4.8 模型发现的,而漏洞本身自 2022 年 5 月 Orchard 资金池上线以来就一直存在。
解释:
一个 zk-SNARK 电路实际上就是一组约束方程。
你要证明的那句话”这笔交易合法“,会被翻译成一堆形如 a × b = c、x + y = z 的等式。证明者要证明的是:”我知道一组秘密输入,能让这张电路里所有约束同时成立“,而验证者不需要看到这些秘密输入,就能确认这一点。
举例: 假设你想证明“我知道某个数 w,它是 35 的平方根之一”(不暴露 w 是 5 还是 -5)。这个电路可能只有一个约束:
w × w = 35
证明者私下用 w=5 满足它,生成证明;验证者只看到证明通过,但不知道 w 是多少。这就是”零知识 + 电路约束”的雏形。
安全漏洞: Orchard 电路中发现了一个约束缺失(missing-constraint)漏洞。它使得在 Orchard 池内可以进行无法被检测、且(除 turnstile 限制外)无上限的 ZEC 增发。
但是请注意上文中很重要的一句话“除 turnstile 限制外”。
什么是 turnstile ?它实际是Zcash的一条共识层会计规则。Zcash 一共有三个屏蔽池,分别是(Sprout / Sapling / Orchard),而每个屏蔽池的协议层都备有一本总账本。
总帐本:协议会追踪总共有多少透明的ZEC流入过这个池子。然后规则是从一个池子中流出的总量,永远不能超过流入该池子的总量。(Zcash 是以zatoshi计算ZEC的金额,1 ZEC=$10^8$ zatoshi,所以总量这个词描述更为准确)
所以实际上这个漏洞影响是有限的甚至可以说,其之前的价格本身应该是已经计价了这个漏洞了。
我们分层来看,
- 池内增发:无上限,且无法检测。
- 提现兑出:会被 turnstile 限制住,最多只能掏空 Orchard 池里全部真实存量。
这个设计本身是针对假设密码学有一天被攻破,所加上的一个守恒限制,没想到在这个情况下起了作用,或许本身这个漏洞就是 Zcash 开发者预留呢?
关于媒体报道中的“不可检测”,实际上说的是官方没有办法在密码学上去证明过去是否被利用过。
有可能有人会想,我计算池子里 Zec 的总量和流入总量做对比不就可以知道是否被利用过了,实际是不行的,因为 Zcash 是屏蔽池,池子里每一张 note 的金额都被同态承诺 + 零知识藏起来了,链上、验证节点、所有人都看不到任何一笔的具体金额,自然也无法把它们加总算出”池内真实总额”。
漏洞:nullifier(作废符)完整性被破坏
Zcash 的 Orchard 池中实际是 note,每次你需要从池子里取钱进行消费实际是在消费 note,而你要防止一张 note 被使用两次(防止双花)你就需要一个 nullifier:花费一张 note 时,你公开它的 nullifier,全网把它记进一张“已花费集合(nullifier set)”;如果某个 nullifier 已经在集合里,这笔花费就会被拒绝。
漏洞就在这里