mt logoMyToken
Market cap:
0%
FGI:
0%
Cryptocurrencies:--
Exchanges --
ETH Gas:--
EN
USD
APP
Ap Store QR Code

Scan Download

Circom 验证库漏洞CVE-2023-33252修复方案

Collect
Share

此前,Beosin 安全研究人员在 SnarkJS 0.6.11及之前的版本 的库中发现了一个严重漏洞, 当该库在验证证明时未对参数进行完整的合法性检查,使得攻击者可以伪造出多个证明通过校验,实现双花攻击。 SnarkJS 是一款用于构建零知识证明的开源 JavaScript 库,广泛应用于 zk-SNARK 技术的实现和优化。

Beosin在提了这个漏洞以后,第一时间联系项目方并协助修复, 目前该漏洞已修复完成。 Beosin提醒所有使用了SnarkJS库的zk项目方可将SnarkJS更新到 0.7.0版本!以确保安全性。

现在,Beosin以长文的形式与大家分享漏洞原理,以及提醒项目方需要注意什么。

前言

Circom是基于Rust开发的零知识证明电路编译器,该团队同时开发了SnarkJS库用于实现证明系统,包括:可信设置、零知识证明的生成和验证等,支持Groth16、PLONK、FFLONK算法。

2. 漏洞原理

Beosin安全实验室漏洞研究人员在SnarkJS小于等于0.6.11版本中发现,当该库在验证证明时未对参数进行完整的合法性检查,使得攻击者可以伪造出多个证明通过校验,实现双花攻击。数学依据: 首先如果要在以太坊中生成和验证zk-SNARK证明,需要使用 F_p-arithmetic 有限域椭圆曲线电路,其中曲线的一般方程如下:

可以发现曲线上的点都会进行一个模p运算,所以电路生成的证明参数s值取值范围为[0,1,…,p-1],那么当SnarkJS的变量范围大于电路取值范围时,存在下列多个具有相同输出的证明参数值:

综上,只要知道了其中一个合法的证明参数s,参数范围内的s+np( n = 1,2,…,n)都可以满足验证计算,于是攻击者在获取到任意验证通过的s,即可构造多个s可以通过校验,具体的攻击流程如下:

上文可知,参数的取值范围由p决定,而不同类型的F_p对应不同的p,需要根据具体使用的零知识算法确定。

3. 漏洞实现

使用snarkjs库进行链下验证时,在groth16Verify函数中并未校验publicSignals参数的取值范围合法性,导致可以伪造证明通过校验:

4. PoC

初始的originalHash验证通过,接着使用刚伪造的attackHash同样验证通过!即同一份proof,可以被多次验证通过,即可造成双花攻击。

此外,由于本文使用ALT_BN128 曲线进行复现,因此共计可以生成6个不同参数通过验证:

4. 修复方案

 

Circom 项目已经针对该通用漏洞进行了修复,涉及到其实现的共计3个算法:

1)groth16_verify.js

2)flonk_verify.js

3)plonk_verify.js

针对此漏洞, Beosin安全团队提醒zk项目方,在进行proof验证时,应充分考虑算法设计在实际实现时,由于代码语言属性导致的安全风险。同时,强烈建议项目方在项目上线之前,寻求专业的安全审计公司进行充分的安全审计,确保项目安全。

5.  漏洞后续

目前该漏洞已经被收录到github advisory database中,且为评分7.5的高危漏洞:

同时该高危漏洞也被更新到npm库中,安装旧版本snarkjs库时会有如下预警信息:

 

Disclaimer: The copyright of this article belongs to the original author and does not represent MyToken(www.mytokencap.com)Opinions and positions; please contact us if you have questions about content