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

Beosin
Beosin 机构得得号

Jun 06, 2023 Beosin是总部位于新加坡的全球知名区块链安全公司,为区块链生态提供代码安全审计,安全风险监控、预警与阻断,虚拟资产被盗追回,KYT/AML等“一站式”安全产品+服务,已为全球2000多个区块链企业服务,保护客户资产5000多亿美元。

摘要: 目前该漏洞已修复完成。Beosin提醒所有使用了SnarkJS库的zk项目方可将SnarkJS更新到 0.7.0版本!以确保安全性。

此前,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 授权链得得发表,并经链得得编辑,转载请注明出处、作者和本文链接

更多精彩内容,关注链得得微信号(ID:ChainDD),或者下载链得得App

分享到:

相关推荐

    评论(0

    Oh! no

    您是否确认要删除该条评论吗?

    分享到微信