比特幣交易所 比特幣交易所
Ctrl+D 比特幣交易所
ads
首頁 > FIL幣 > Info

Beosin | 深度剖析零知識證明zk-SNARK漏洞:為什么零知識證明系統并非萬無一失?_COM

Author:

Time:1900/1/1 0:00:00

隨著數字資產和區塊鏈技術的快速發展,數字隱私保護和安全性成為了越來越受關注的話題。在這個背景下,一種名為"零知識證明(Zero-Knowledge Proof)"的技術正在逐漸嶄露頭角。

零知識證明技術可以在不泄露任何信息的情況下證明某些事情的真實性,被廣泛應用于保護隱私和安全性。其中,基于零知識證明技術的zk-SNARK近期備受矚目,成為數字資產和區塊鏈技術領域的熱門話題,但有一些安全問題卻往往被我們忽視。

Beosin將陸續推出zk零知識證明安全研究,第一篇,本文將深入探討zk-SNARK的背景,深度剖析零知識證明zk-SNARK漏洞:輸入假名漏洞是如何被挖掘出來的?

zk-SNARK(Zero-Knowledge Succinct Non-Interactive Argument of Knowledge)是一種基于零知識證明的技術,可以在不泄露真實信息的情況下證明某個聲明的真實性。

它是一種非常高效的零知識證明技術,可以在非常短的時間內生成和驗證證明,同時保護隱私和安全性。

零知識證明項目Semaphore上曾經被發現了一個可以導致雙花的輸入假名漏洞,漏洞提出者poma給出了兩筆成功的示例交易:

圖源:https://github.com/semaphore-protocol/semaphore/issues/16

該漏洞影響范圍非常廣,不止涉及到眾多知名zkSNARKs第三方庫,連眾多DApp項目方也不能幸免,本文最后將列舉出各個項目方具體的漏洞代碼以及修復方案,我們先對輸入假名漏洞進行詳細介紹。

Semaphore項目允許以太坊用戶在不透漏其原始身份的情況下,以某個團隊成員的身份發送投票等操作,其中所有的團隊成員組成了一棵默克爾樹,每個成員是一個葉子結點。合約需要團隊成員提供一個零知識證明,以證明其身份的合法性。為了防止身份偽造,每個證明只能使用一次,因此合約中會存儲已經驗證過的證明列表,如果用戶提供了使用過的證明,程序就會報錯。具體的實現代碼如下:

圖源:https://github.com/semaphore-protocol/semaphore/blob/602dd57abb43e48f490e92d7091695d717a63915/semaphorejs/contracts/Semaphore.sol#L83

Beosin:穩定幣協議Steadifi遭到攻擊損失約114萬美元:金色財經報道,據Beosin EagleEye監測發現,穩定幣協議Steadifi遭到攻擊,攻擊者獲取了協議部署錢包的控制權。攻擊者已將所有金庫(借貸和策略)投資組合的所有權轉移至自己控制的錢包(0x9cf71F2ff126B9743319B60d2D873F0E508810dc),目前,攻擊者已在Arbitrum和Avalanche上耗盡了所有可借出資金,并通過跨鏈橋將資產兌換成以太幣轉移到以太坊主網,被盜資金約1,140,000美元。

Steadifi正與攻擊者進行談判,提供10%的賞金以換回剩余90%的被盜資產。[2023/8/8 21:31:18]

可以看到,上述代碼首先調用 verifyProof 校驗零知識證明的合法性,接著通過證明參數nullifiers_hash 校驗該證明是否是初次使用,但由于未對 nullifiers_hash 進行完整的合法性檢查,使得攻擊者可以偽造出多個證明通過校驗,實現雙花攻擊。具體地說,由于合約變量類型uint256能夠表示的數值范圍遠大于零知識證明電路,而此處代碼僅考慮了 nullifiers_hash 本身是否已被使用,未限制合約中的 nullifiers_hash 的取值范圍,使得攻擊者利用密碼學中的模運算可以偽造多個證明通過合約校驗。因為參數的取值范圍涉及到一些零知識證明相關的數學知識,并且采用不同的零知識證明算法對應不同的取值范圍,因此后文將詳細介紹。

首先如果要在以太坊中生成和驗證zk-SNARK證明,需要使用 F_p-arithmetic 有限域橢圓曲線電路,其中曲線的一般方程如下:

可以發現曲線上的點都會進行一個模p運算,所以電路生成的證明參數s值取值范圍為[0,1,…,p-1],但是鏈上合約的變量類型uint256取值范圍為 [0,115792089237316195423570985008687907853269984665640564039457584007913129639935],那么當合約的變量范圍大于電路取值范圍時,存在下列多個具有相同輸出的證明參數值:

綜上,只要知道了其中一個合法的證明參數s,uint256范圍內的s+np( n = 1,2,…,n)都可以滿足驗證計算,于是攻擊者在獲取到任意驗證通過的s,即可構造max(uint256)/p個 s都可以通過校驗,具體的攻擊流程如下:

Beosin:Themis Protocol被攻擊事件分析:據區塊鏈安全審計公司Beosin旗下Beosin EagleEye安全風險監控、預警與阻斷平臺監測顯示,2023年6月28日DeFi借貸協議Themis Protocol遭到攻擊,攻擊者獲利約37萬美元,Beosin Trace追蹤發現已有130,471個USDC、58,824個USDT和94個ETH被盜,目前,被盜資金被轉移到以太坊的0xDb73eb484e7DEa3785520d750EabEF50a9b9Ab33地址。其攻擊的原因在于預言機實現存在問題,導致預言機被操縱。

攻擊交易為:0xff368294ccb3cd6e7e263526b5c820b22dea2b2fd8617119ba5c3ab8417403d8。攻擊的核心是攻擊者在借款前,用大量WETH兌換wstETH,使得預言機獲取價格時被操縱,導致攻擊者僅用55WETH借出317WETH。

如圖,在getAssetPrice函數調用Balancer: Vault.getPoolTokens函數時,wstETH與ETH數量從正常的2,423 : 2,796被操縱為0.238 : 42,520.從而操縱了預言機。[2023/6/28 22:05:01]

上文可知,參數的取值范圍由p決定,而不同類型的F_p對應不同的p,需要根據具體使用的零知識算法確定,如:

EIP-196 中定義的BN254 曲線(也稱為 ALT_BN128 曲線) p = 21888242871839275222246405745257275088548364400416034343698204186575808495617

circom2 引入了兩個新的素數,即BLS12-381曲線  p = 52435875175126190479447740508185965837690552500527637822603658699938581184513

以ALT_BN128 曲線為例,共計可以生成5個不同的證明參數通過驗證,計算過程如下:

由于Semaphore項目本身代碼已經更改,重新部署整個項目較為繁雜,因此我們使用目前常用的零知識證明編譯器circom編寫PoC復現整個攻擊過程。為了方便大家更好的理解整個流程,這里我們先以circom為例,介紹Groth16算法的零知識證明生成和驗證過程。

圖源:https://docs.circom.io/

Beosin:Jumpnfinance項目發生Rugpull,涉及金額約115萬美元:金色財經報道,據Beosin EagleEye平臺監測顯示,Jumpnfinance項目Rugpull。攻擊交易為0x48333962e6e946748a26d6222db95ce97e76c9ed3917123a7c9f2731f896b72c。Beosin安全團隊分析發現攻擊者首先調用0xe156合約的0x6b1d9018()函數,提取了該合約中的用戶資產,存放在攻擊者地址上(0xd3de02b1af100217a4bc9b45d70ff2a5c1816982)。目前被盜資金中2100 BNB ($581,700)已轉入Tornado.Cash,剩余部分2,058 BNB($571,128)還存放在攻擊者地址,Beosin安全團隊將持續跟蹤。Beosin Trace將對被盜資金進行持續追蹤。[2022/10/10 12:51:13]

1.項目方需要設計一個算術電路并使用 circom 語法將其編寫為一個電路描述文件   *.circom

2.編譯電路文件,并將其轉化為 R1CS 的電路描述文件

3.使用snarkjs庫根據輸入文件 input.json 計算出對應的 witness

4.接著通過可信設置生成一個證明密鑰 Proving key 和驗證密鑰 Validation key,其中Proving key用于生成證明Proof, Validation key 用于驗證Proof,最后用戶利用密鑰生成對應的零知識證明Proof

5.驗證用戶的證明

接下來我們將按照上述流程分步進行介紹。

為了方便大家理解,我們直接使用circom官方的demo,具體代碼如下:

pragma circom 2.0.0;template Multiplier2() {    signal input a;    signal input b;    signal output c;    c <== a*b; }component main = Multiplier2();

該電路中有兩個輸入信號a和b,一個輸出信號c,并且c的值是a和b相乘的結果

使用下列命令行編譯multiplier2.circom,并將其轉化為R1CS:

circom multiplier2.circom --r1cs --wasm --sym --c編譯后會生成4個文件,其中

?--r1cs:生成的circuit.r1cs是二進制格式的電路約束文件

Beosin解析Reaper Farm遭攻擊事件:_withdraw中owner地址可控且未作任何訪問控制:8月2日消息,據 Beosin EagleEye 安全輿情監控數據顯示,Reaper Farm 項目遭到黑客攻擊,Beosin 安全團隊發現由于_withdraw 中 owner 地址可控且未作任何訪問控制,導致調用 withdraw 或 redeem 函數可提取任意用戶資產。攻擊者(0x5636 開頭)利用攻擊合約(0x8162 開頭)通過漏洞合約(0xcda5 開頭)提取用戶資金,累計獲利 62 ETH 和 160 萬 DAI,約價值 170 萬美元,目前攻擊者(0x2c17 開頭)已通過跨鏈將所有獲利資金轉入 Tornado.Cash。[2022/8/2 2:54:18]

?--wasm:生成的multiplier2_js文件夾包含wasm匯編代碼,和生成witness所需的其他文件目錄(generate_witness.js、multiplier2.wasm)

?--sym:生成文件夾multiplier2.sym,是一個符號文件,用于調試或以注釋模式打印約束系統

?--c:生成文件夾multiplier2_cpp,包含生成witness所需的c代碼文件

注意:生成witness有兩種方式,一種是使用wasm,一種是使用剛生成的C++代碼,如果是大型電路的話使用C++代碼比wasm效率更高

在multiplier2_js文件夾下創建input.json文件,該文件包含了以標準json格式編寫的輸入,此時使用字符串而不是數字,是因為js不能準確處理大于2^{53}的數,針對指定的 input.json 生成對應的witness:

node generate_witness.js multiplier2.wasm input.json witness.wtns3.4 可信設置

該步驟主要是選取零知識證明需要的橢圓曲線類型,以及生成一系列原始密鑰*.key文件,其中multiplier2_0000.zkey包含證明密鑰、驗證密鑰,multiplier2_0001.zkey則是驗證密鑰,最終導出的驗證密鑰文件是verification_key.json

snarkjs powersoftau new bn128 12 pot12_0000.ptau -vsnarkjs powersoftau contribute pot12_0000.ptau pot12_0001.ptau --name="First contribution" -vsnarkjs powersoftau prepare phase2 pot12_0001.ptau pot12_final.ptau -vsnarkjs groth16 setup multiplier2.r1cs pot12_final.ptau multiplier2_0000.zkeysnarkjs zkey contribute multiplier2_0000.zkey multiplier2_0001.zkey --name="1st Contributor Name" -vsnarkjs zkey export verificationkey multiplier2_0001.zkey verification_key.json3.5 生成證明

LLE智能合約已通過Beosin(成都鏈安)的安全審計:據官方消息,Beosin(成都鏈安)今日已完成LLE智能合約項目的安全審計服務。

獵豹金融生態系統(Leopard lending ecology)是在以太坊區塊鏈上的智能協議,以該協議為中心建立貨幣服務市場,服務市場是基于資產借貸需求,以計算得出利率。資產的供應商直接與協議進行交互,從而賺取浮動利率,而無需等待協商利率或抵押品等條款。

創始人Willians表示:我們LLE智能合約的整體設計清晰,邏輯縝密,代碼安全可靠,具備了區塊鏈上頂級去中心化金融項目條件之一。

合約地址:0xa1521aA6FE752195418ddbADB5A0c331608416B1;

審計報告編號:202009222010。[2020/9/24]

利用snarkjs有兩種方式可以生成證明,一種是命令行,一種是腳本生成。由于我們需要構造攻擊向量,所以這里主要使用腳本生成。

3.5.1 生成正常 publicSignal

snarkjs groth16 prove multiplier2_0001.zkey witness.wtns proof.json public.json該命令會輸出兩個文件,其中proof.json是生成的證明文件,public.json是公共輸入值。

async function getProof() {    let inputA = "7"    let inputB = "11"    const { proof, publicSignals } = await snarkjs.groth16.fullProve({ a: inputA, b: inputB }, "Multiplier2.wasm", "multiplier2_0001.zkey")    console.log("Proof: ")    console.log(JSON.stringify(proof, null, 1));

   let q = BigInt("21888242871839275222246405745257275088548364400416034343698204186575808495617")    let originalHash = publicSignals    let attackHash = BigInt(originalHash) + q    console.log("originalHash: " + publicSignals)    console.log("attackHash: " + attackHash。

生成的證明Proof、原始驗證參數originalHash和攻擊參數attackHash如下圖所示:

證明的驗證方式同樣也有兩種,一種是使用snarkjs庫進行驗證,一種是合約驗證。我們這里主要使用鏈上合約的驗證方式驗證原始證明參數originalHash、攻擊證明參數attackHash。

這里我們使用snarkjs自動生成一個驗證合約verifier.sol,注意最新版本0.6.10的snarkjs生成的合約已經修復了這個問題,所以我們使用舊版本生成合約:

snarkjs zkey export solidityverifier multiplier2_0001.zkey verifier.sol合約關鍵代碼如下:

function verify(uint[] memory input, Proof memory proof) internal view returns (uint) {        VerifyingKey memory vk = verifyingKey();        require(input.length + 1 == vk.IC.length,"verifier-bad-input");        // Compute the linear combination vk_x        Pairing.G1Point memory vk_x = Pairing.G1Point(0, 0);        for (uint i = 0; i < input.length; i++)            vk_x = Pairing.addition(vk_x, Pairing.scalar_mul(vk.IC[i + 1], input[i]));        vk_x = Pairing.addition(vk_x, vk.IC);        if (!Pairing.pairingProd4(            Pairing.negate(proof.A), proof.B,            vk.alfa1, vk.beta2,            vk_x, vk.gamma2,            proof.C, vk.delta2        )) return 1;        return 0;}此時,使用originalHash驗證通過:

最后使用剛偽造的attackHash:

21888242871839275222246405745257275088548364400416034343698204186575808495694,同樣驗證通過!即同一份proof,可以被多次驗證通過,即可造成雙花攻擊。

此外,由于本文使用ALT_BN128 曲線進行復現,因此共計可以生成5個不同參數通過驗證:

Semaphore 項目已經針對該漏洞進行了修復,具體修復代碼如下:

圖源:https://github.com/semaphore-protocol/semaphore/blob/0cb0ef3514bc35890331379fd16c7be071ada4f6/packages/contracts/contracts/base/SemaphoreVerifier.sol#L42

圖源:https://github.com/semaphore-protocol/semaphore/blob/0cb0ef3514bc35890331379fd16c7be071ada4f6/packages/contracts/contracts/base/Pairing.sol#L94

但是該漏洞屬于實現上的通用漏洞,經過我們Beosin安全團隊的研究發現,眾多知名的零知識證明算法組件和DApp項目都受到該漏洞的影響,絕大部分后續進行了及時修復。以下列舉出部分項目方的修復方案:

ethsnarks:

圖源 https://github.com/HarryR/ethsnarks/commit/34a3bfb1b0869e1063cc5976728180409cf7ee96

snarkjs:

圖源:https://github.com/iden3/snarkjs/commit/25dc1fc6e311f47ba5fa5378bfcc383f15ec74f4

heiswap-dapp:

圖源:https://github.com/kendricktan/heiswap-dapp/commit/de022ffc9ffdfa4e6d9a7b51dc555728e25e9ca5#diff-a818b8dfd8f87dea043ed78d2e7c97ed0cda1ca9aed69f9267e520041a037bd5

EY Blockchain:

圖源:https://github.com/EYBlockchain/nightfall/pull/96/files

此外,還有部分項目未能及時修復,Beosin安全團隊已與項目方取得聯系,正在積極協助修復。

針對此漏洞,Beosin安全團隊提醒zk項目方,在進行proof驗證時,應充分考慮算法設計在實際實現時,由于代碼語言屬性導致的安全風險。同時,強烈建議項目方在項目上線之前,尋求專業的安全審計公司進行充分的安全審計,確保項目安全。

Beosin

企業專欄

閱讀更多

金色薦讀

金色財經 善歐巴

Chainlink預言機

區塊律動BlockBeats

白話區塊鏈

金色早8點

Odaily星球日報

MarsBit

Arcane Labs

深潮TechFlow

Tags:NBSBSPPROCOMnbs幣官網BSPAY價格DeSpace ProtocolCOMOS Finance

FIL幣
PEPE再掀投機熱潮 下一個Meme Coin是什么?_NBS

近期的 PEPE 一直在話題熱榜上,改變了“不溫不火”的市場現狀,重新點燃了用戶心中靠 Crypto 一夜暴富的夢想.

1900/1/1 0:00:00
韭菜收割指南:復盤XIRTAM從開盤到跑路的一夜_TAM

作者:Go2Mars Research2023年5月3日,當大眾還在享受著五一假期的余溫時,對于許多加密圈的朋友而言,這個夜晚并不輕松.

1900/1/1 0:00:00
Lido 將如何漸進地去中心化_ETH

Lido 實際上是在以太坊上的中間件或一組軟件。從作為 Lido DAO 的一名貢獻者的角度,我認為 Lido DAO 成員和投票者對寫進 Lido 協議的行動所反映的精神和原則是不斷演變的.

1900/1/1 0:00:00
盤點2023年值得關注的以太坊改進提案_NBS

以太坊開發者社區不斷突破創新界限,以改善去中心化應用程序 (dApp) 的用戶體驗。EIP 和 ERC 分別是提案和正式的標準,旨在改進以太坊網絡的功能.

1900/1/1 0:00:00
以太坊誕生之初的“中國故事”_ALI

以下內容為香港 Web3 嘉年華速記Jerry Liu,水滴資本聯合創始人杜宇,萬向區塊鏈實驗室負責人Roland Sub.

1900/1/1 0:00:00
項目跑路也能保證資金安全?體驗一下 zkLink 資金災難逃離測試_INK

來源:zkLink 社區加密世界經常被形容為黑暗森林,這是一個充滿機遇,但也危險重重的新大陸。黑客攻擊和程序漏洞時刻威脅著用戶資金安全,更有甚者,詐騙項目卷款跑路的事情也時有發生,大大提高用戶篩.

1900/1/1 0:00:00
ads