查看原文
其他

漏洞复现 | Beosin 提交Circom 验证库漏洞CVE-2023-33252,并附修复方案,zk项目方需警惕!

Beosin Beosin 2023-10-16

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


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


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


前言

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


https://docs.circom.io/


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个算法:


https://github.com/iden3/snarkjs/issues/358


1)groth16_verify.js


https://github.com/iden3/snarkjs/commit/7f462cc932191348a057e6e18f377154369104fc#


2)flonk_verify.js



3)plonk_verify.js



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


5.  漏洞后续


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


https://github.com/advisories/GHSA-xp5g-jhg3-3rg2


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



Beosin作为一家全球领先的区块链安全公司,在全球10多个国家和地区设立了分部,业务涵盖项目上线前的代码安全审计、项目运行时的安全风险监控、预警与阻断、虚拟货币被盗资产追回、安全合规KYT/AML等“一站式”区块链安全产品+服务,目前已为全球3000多个区块链企业提供安全技术服务,审计智能合约超过3000份,同时,Beosin也提供上币项目的安全评估以及提供符合各地监管要求的合规评估、VaaS自动化上币审计服务、交易所渗透服务、交易所安全建设咨询服务等安全解决方案。欢迎点击公众号留言框,与我们联系。

 近期热点文章阅读:

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存