zkSNARKs 合约库「输入假名」漏洞致众多混币项目爆雷

本文作者:p0n1(安比实验室)

大量零知识证明项目由于错误地使用了某个 zkSNARKs 合约库,引入「输入假名 (Input Aliasing) 」漏洞,可导致伪造证明、双花、重放等攻击行为发生,且攻击成本极低。众多以太坊社区开源项目受影响,其中包括三大最常用的 zkSNARKs 零知开发库 snarkjs、ethsnarks、ZoKrates,以及近期大热的三个混币(匿名转账)应用 hopper、Heiswap、Miximus。这是一场由 Solidity 语言之父 Chris 两年前随手贴的一段代码而引发的血案。

双花漏洞:最初暴露的问题

semaphore 是一个使用零知识证明技术的匿名信号系统,该项目由著名开发者 barryWhiteHat 此前的混币项目演化而来。

俄罗斯开发者 poma 最先指出该项目可能存在双花漏洞[1]。
zkSNARKs 合约库「输入假名」漏洞致众多混币项目爆雷_第1张图片
问题出在第 83 行代码[2],请仔细看。zkSNARKs 合约库「输入假名」漏洞致众多混币项目爆雷_第2张图片
该函数需要调用者构造一个零知识证明,证明自己可从合约中提走钱。为了防止「双花」发生,该函数还读取「废弃列表」,检查该证明的一个指定元素是否被标记过。如果该证明在废弃列表中,则合约判定校验不通过,调用者无法提走钱。开发者认为,这样一来相同的证明就无法被重复提交获利,认为此举可以有效防范双花或重放攻击。

然而事与愿违,这里忽视了一个致命问题。攻击者可根据已成功提交的证明,利用「输入假名」漏洞,对原输入稍加修改便能迅速「伪造证明」,顺利通过合约第 82 行的零知识证明校验,并绕过第 83 行的防双花检查。

该问题最早可追溯到 2017 年,由 Christian Reitwiessner 大神,也就是 Solidity 语言的发明者,提供的 zkSNARKs 合约密码学实现示例[3]。其后,几乎以太坊上所有使用 zkSNARKs 技术的合约,都照用了该实现。因此都可能遭受以下流程的攻击。
zkSNARKs 合约库「输入假名」漏洞致众多混币项目爆雷_第3张图片

混币应用:该安全问题的重灾区

零知识证明技术在以太坊上最早和最广泛的应用场景是

你可能感兴趣的:(安全技术,区块链,智能安全合约,零知识漏洞分析)