摘要:今天,我們繼續(xù)介紹文獻中提到的以太坊合約的安全性弱點與案例。隨機數(shù)生成的字節(jié)碼執(zhí)行是確定性的。但是,一個惡意的礦工可能嘗試操縱自己生成的區(qū)塊來影響隨機數(shù)的生成與合約的執(zhí)行結(jié)果。合約中的錢將被偷走。
今天,我們繼續(xù)介紹文獻中提到的以太坊合約的安全性弱點與案例。
數(shù)據(jù)保密
Solidity 智能合約中的變量分 public 和 private 兩種。Private 變量表示這個數(shù)值不能被其他合約直接讀取。
但是,將一個變量標(biāo)記為 private 不意味著里面的信息就是保密的。因為以太坊是公開的,每次合約函數(shù)執(zhí)行的字節(jié)碼,參數(shù)都是公開的,任何人都可以推斷出每次函數(shù)執(zhí)行后是否修改了變量,修改后的數(shù)值是多少。Private 只是能夠保證其他合約執(zhí)行的時候,無法讀取其中的變量罷了。
然而,一些本應(yīng)該隱藏玩家數(shù)據(jù)的游戲,卻錯誤地使用了這一點。以下是一個示例:
兩個玩家在玩一個賭博游戲,每個玩家選一個正整數(shù),兩個正整數(shù)加起來的奇偶性,決定了獲勝者。
存儲玩家選擇的變量是 players, 這個變量具有 private 屬性。玩家通過調(diào)用智能合約函數(shù)選數(shù)的時候,決策并不是保密的。
為了實現(xiàn)保密性,更好的方式是使用一個稱為“委托”的密碼學(xué)原語。當(dāng)玩家需要秘密地做出一個決定時,可以將 sha3(決策內(nèi)容,隨機數(shù)) 得到的哈希值存到合約里。當(dāng)玩家需要公開自己選擇的時候,將 決策內(nèi)容 與 隨機數(shù) 公開,并由智能合約驗證哈希值與先前存儲的是否一致??梢詫崿F(xiàn)類似于“先在紙上秘密寫下選擇,到后面一個環(huán)節(jié)再亮出來”的功能。
隨機數(shù)生成
EVM 的字節(jié)碼執(zhí)行是確定性的。因此,如果智能合約想生成一個隨機數(shù),就需要通過一個隨機數(shù)種子生成一個偽隨機數(shù)。而隨機數(shù)種子的選取方式,對生成隨機數(shù)的公平性有很大的影響。
一個常用的做法是,使用一個給定時間或給定高度區(qū)塊的哈希值或時間戳。這件事情在給定區(qū)塊被確認以后,在每個礦工看來都是一樣的。
看起來這是一個公平的做法,因為沒有人能預(yù)測未來的區(qū)塊。但是,一個惡意的礦工可能嘗試操縱自己生成的區(qū)塊來影響隨機數(shù)的生成與合約的執(zhí)行結(jié)果。一個分析表示,一個控制少數(shù)算力的礦工,只需要投入 50 個比特幣就可以顯著地改變輸出結(jié)果的概率分布。
另一個方式是使用“延時委托協(xié)議”。在這個協(xié)議中,每個參與者選擇一個秘密的隨機數(shù),并將哈希值廣播給其他人。在晚些時候,所有參與者公布它們選取的秘密隨機數(shù),或者丟失押金。最終隨機數(shù)由所有公布的秘密隨機數(shù)和一個公開的算法生成。攻擊者可以在“其他所有人都已經(jīng)公布了隨機數(shù),自己還沒有公布”時,預(yù)先計算最終生成的隨機數(shù),如果生成的結(jié)果它不滿意,就通過拒絕公布自己選擇的隨機數(shù)方式,來使這個結(jié)果無效。當(dāng)然,攻擊者要損失一些押金。所以,押金的設(shè)定要足夠高,高于隨機數(shù)生成中改變結(jié)果可能帶來的收益。
不可預(yù)測狀態(tài)
一個合約的狀態(tài)包括合約變量和合約余額。一般情況下,當(dāng)用戶通過一筆交易調(diào)用合約函數(shù)的時候,從交易廣播到交易被加入?yún)^(qū)塊之間,可能有其他的交易改變了合約的狀態(tài)。也就是說,當(dāng)用戶發(fā)起一筆交易時,并不能確定這筆交易被執(zhí)行時,合約的狀態(tài)是什么。
一個基于 library 和不可預(yù)測狀態(tài)的攻擊
下面我們來看一個例子,以下的 Solidity 代碼定義了一個名為 Set 的 library。
下面是一個名為 SetProvider 的合約,提供了一個 Set library 的地址,合約擁有者可以修改這個地址,任何人/合約可以獲取這個地址。
假設(shè) Bob 合約是一個使用 SetProvider 的誠實用戶,他的代碼如下:
Bob 記錄了一個 SetProvider 合約的地址,在 getSetVersion() 中,使用這個地址獲取了一個 Set library 的版本號。
現(xiàn)在,假設(shè) SetProvider 合約的控制者是個壞人。他制造了一個惡意的 Set library, 希望偷得一些錢存到他自己的錢包地址 0x42 中。
如果合約 SetProvider 中 setLibAddr 的地址被修改為 MaliciousSet 的地址, Bob 合約中調(diào)用 getSetVersion() 函數(shù)時,會調(diào)用 MaliciousSet 的 version() 函數(shù),而不是 Set 的。因為 Bob 合約中將 Set 聲明為一個 library, 所以對 version() 的調(diào)用采用的是 delegatecall 模式。 delegatecall 模式意味著轉(zhuǎn)賬操作 attackerAddr.send(this.balance); 是從 Bob 合約中轉(zhuǎn)賬出來。 Bob 合約中的錢將被偷走。
上述例子說明了,對 library 函數(shù)的調(diào)用使用的是較為危險的 delegatecall 模式。因此合約編寫者在使用其他合約地址作為 library 時,一定要保證通過 library 加載進來的代碼是自己可控的。比如,手動指定一個已經(jīng)在區(qū)塊鏈上不可修改的 library 的地址。而不是在本例中依靠于一個不可靠的 SetProvider 合約來獲取 library 的地址。
另外,“不可預(yù)測狀態(tài)”問題也加劇了這件事情。即使在調(diào)用 Bob 合約的 getSetVersion() 函數(shù)時, SetProvider 指向的是誠實的 Set library. 攻擊者也可以在這一交易還沒有被加入?yún)^(qū)塊的時候,通過發(fā)起一筆交易費數(shù)額較大的交易,搶在 getSetVersion() 被加入?yún)^(qū)塊之前,將 SetProvider 的指向修改為 MaliciousSet。
Conflux 是致力于打造下一代高性能的 DAPP 公鏈平臺
歡迎關(guān)注我們的微信公眾號:Conflux中文社區(qū)(Conflux-Chain)
添加微信群管理員 Confluxgroup 回復(fù)“加群”加入 Conflux官方交流群
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/24552.html
摘要:很多以太坊的智能合約控制著有實際價值的數(shù)字資產(chǎn)。這幾期為大家?guī)硪黄陮σ蕴缓霞s攻擊調(diào)研的文獻,來幫助大家避免以太坊智能合約設(shè)計中的一些可能導(dǎo)致安全性問題的弱點。攻擊攻擊是以太坊歷史上最著名的攻擊,盜走了價值萬美元的以太幣。 showImg(https://segmentfault.com/img/bVbnRDB?w=1080&h=460); 很多以太坊的智能合約控制著有實際價值的數(shù)...
摘要:很多以太坊的智能合約控制著有實際價值的數(shù)字資產(chǎn)。這幾期為大家?guī)硪黄陮σ蕴缓霞s攻擊調(diào)研的文獻,來幫助大家避免以太坊智能合約設(shè)計中的一些可能導(dǎo)致安全性問題的弱點。攻擊攻擊是以太坊歷史上最著名的攻擊,盜走了價值萬美元的以太幣。 showImg(https://segmentfault.com/img/bVbnRDB?w=1080&h=460); 很多以太坊的智能合約控制著有實際價值的數(shù)...
摘要:很多以太坊的智能合約控制著有實際價值的數(shù)字資產(chǎn)。這幾期為大家?guī)硪黄陮σ蕴缓霞s攻擊調(diào)研的文獻,來幫助大家避免以太坊智能合約設(shè)計中的一些可能導(dǎo)致安全性問題的弱點。攻擊攻擊是以太坊歷史上最著名的攻擊,盜走了價值萬美元的以太幣。 showImg(https://segmentfault.com/img/bVbnRDB?w=1080&h=460); 很多以太坊的智能合約控制著有實際價值的數(shù)...
閱讀 3165·2021-11-24 10:47
閱讀 3928·2021-11-02 14:43
閱讀 2321·2021-09-26 10:15
閱讀 2688·2021-09-08 09:35
閱讀 641·2019-08-30 12:45
閱讀 2841·2019-08-29 17:04
閱讀 3341·2019-08-26 14:05
閱讀 1365·2019-08-26 12:10